Как рисовать на виджете?
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 06.09.22 13:09
Оценка: :)))
Есть некоторый виджет wgt типа QWidget. Как на нём осуществить рисование? (Рисование точек, линий, прямоугольников, закраска областей).

Читаю книгу Макса Шлее "Qt 5.3. Профессиональное программирование на C++" и не могу найти там материалов про то, как рисовать на виджетах.
1613 г. = 2024 г.
Re: Как рисовать на виджете?
От: Нomunculus Россия  
Дата: 06.09.22 13:40
Оценка:
Здравствуйте, RussianFellow, Вы писали:

Специально даже качнул книгу.
Глава 18.
Re: Как рисовать на виджете?
От: alpha21264 СССР  
Дата: 06.09.22 13:45
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Есть некоторый виджет wgt типа QWidget. Как на нём осуществить рисование? (Рисование точек, линий, прямоугольников, закраска областей).


Вот так:
void myWidget::paintEvent(QPaintEvent *event )
{
   QPainter Painter( this );

   Painter.fillRect( 0,0,width(),height(),QColor(97,127,127) );
   // Ещё чего-нибудь.
}


А потом так рраз!

    MainWindow->myWidget->repaint();


И оно нарисовалось.

PS.
Не ругайтесь на новичка. Рисовать через вызов события — это действительно неочевидно.

Течёт вода Кубань-реки куда велят большевики.
Re[2]: Как рисовать на виджете?
От: Нomunculus Россия  
Дата: 06.09.22 13:49
Оценка: 6 (1) +1
Здравствуйте, alpha21264, Вы писали:

A>PS.

A>Не ругайтесь на новичка. Рисовать через вызов события — это действительно неочевидно.

Действительно. Учитывая что вся работа на MFC на этом основана
Re: Как рисовать на виджете?
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 06.09.22 13:53
Оценка:
И ещё вопрос: как выводить текст в графическом режиме?
1613 г. = 2024 г.
Re[3]: Как рисовать на виджете?
От: alpha21264 СССР  
Дата: 06.09.22 14:03
Оценка:
Здравствуйте, Нomunculus, Вы писали:

A>>PS.

A>>Не ругайтесь на новичка. Рисовать через вызов события — это действительно неочевидно.

Н>Действительно. Учитывая что вся работа на MFC на этом основана


Ну... Я MFC в последний раз видел в прошлом веке.
И... Я подозреваю, что там другие события.
Например, в прошлой версии Qt было необязательно делать myWidget->repaint();

Течёт вода Кубань-реки куда велят большевики.
Re[4]: Как рисовать на виджете?
От: Нomunculus Россия  
Дата: 06.09.22 14:04
Оценка:
Здравствуйте, alpha21264, Вы писали:

A>Ну... Я MFC в последний раз видел в прошлом веке.


Я тоже. Ну или в нулевых. Помнится что-то
Re[2]: Как рисовать на виджете?
От: alpha21264 СССР  
Дата: 06.09.22 14:05
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>И ещё вопрос: как выводить текст в графическом режиме?


Ну, вот это ты должен сам догадаться. Я не говорил про
Painter->drawText(...);

Течёт вода Кубань-реки куда велят большевики.
Re[2]: Как рисовать на виджете?
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 06.09.22 14:16
Оценка:
Здравствуйте, Нomunculus, Вы писали:

Н>Здравствуйте, RussianFellow, Вы писали:


Н>Специально даже качнул книгу.

Н>Глава 18.

Просмотрел, но там мало про это написано. Как я понимаю, надо использовать QLabel, которую потом надо вставлять в QWidget?
Нельзя ли тем не менее привести образец кода?
1613 г. = 2024 г.
Re[3]: Как рисовать на виджете?
От: Нomunculus Россия  
Дата: 06.09.22 14:36
Оценка: +3
Здравствуйте, RussianFellow, Вы писали:

Нет. QLabel там для примера. Неужели сложно догадаться. Примеры кода приводить не буду. Тебе лень пальцем пощевелить, а других просишь работать за тебя. Привык что тебе все разжёвывают.
Re[4]: Как рисовать на виджете?
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 07.09.22 10:40
Оценка:
Вот код (рисование прямоугольника):

QWidget *myWidget;

// ...

QPainter* myPainter = new QPainter(myWidget);
myPainter->begin(myWidget);
myPainter->setRenderHint(QPainter::Antialiasing);
myPainter->setBrush(QColor(255,255,255));
myPainter->drawRect(0,0,wyWidget->width(),myWidget->height());
myPainter->end();


В этом коде всё правильно?
1613 г. = 2024 г.
Re[5]: Как рисовать на виджете?
От: Нomunculus Россия  
Дата: 07.09.22 10:53
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>В этом коде всё правильно?


В чем проблема попробовать? Компьютера боишься? Ну и как сказали, это лишь один из способов, без создания своего наследника от QWidget
Re: Как рисовать на виджете?
От: Igore Россия  
Дата: 08.09.22 08:31
Оценка: +1
Здравствуйте, RussianFellow, Вы писали:

RF>Есть некоторый виджет wgt типа QWidget. Как на нём осуществить рисование? (Рисование точек, линий, прямоугольников, закраска областей).

Мне вот прям интересно стало, что такое ты хочешь сделать что нужно именно ручное рисование? Хотеслоь бы картинку увидеть, всё что мне приходит в голову это в telegram delegat-ы, там ручное рисование чтобы было быстро, для обычных случаем widget на стандартных элементах должен покрывать 95% случаем.
Re[2]: Как рисовать на виджете?
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 08.09.22 09:23
Оценка:
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, RussianFellow, Вы писали:


RF>>Есть некоторый виджет wgt типа QWidget. Как на нём осуществить рисование? (Рисование точек, линий, прямоугольников, закраска областей).

I>Мне вот прям интересно стало, что такое ты хочешь сделать что нужно именно ручное рисование? Хотеслоь бы картинку увидеть, всё что мне приходит в голову это в telegram delegat-ы, там ручное рисование чтобы было быстро, для обычных случаем widget на стандартных элементах должен покрывать 95% случаем.

Есть некоторая таблица myTable типа QTableWidget. И в её клетках я хочу программно нарисовать какие-то рисунки. Как мне это сделать?
1613 г. = 2024 г.
Re[3]: Как рисовать на виджете?
От: SаNNy Россия  
Дата: 08.09.22 09:31
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Есть некоторая таблица myTable типа QTableWidget. И в её клетках я хочу программно нарисовать какие-то рисунки. Как мне это сделать?


https://doc.qt.io/qt-6/qtwidgets-itemviews-stardelegate-example.html
Re[3]: Как рисовать на виджете?
От: Нomunculus Россия  
Дата: 08.09.22 09:39
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Есть некоторая таблица myTable типа QTableWidget. И в её клетках я хочу программно нарисовать какие-то рисунки. Как мне это сделать?


Ты реально третий день не можешь это понять?
Re[3]: Как рисовать на виджете?
От: Igore Россия  
Дата: 08.09.22 09:43
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Есть некоторая таблица myTable типа QTableWidget. И в её клетках я хочу программно нарисовать какие-то рисунки. Как мне это сделать?

Берешь картинки и кладешь их в ресурсы, берешь QLabel устанавливаешь ему setPixmap, может еще и scaledContents, и устанавливаешь эту QLabel(или наследника) как виджет для ячейки, если нужна логика выделяешь как отдельный класс отнаследованный от QLabel и там всё прописываешь.
Отредактировано 08.09.2022 9:45 Igore . Предыдущая версия .
Re[4]: Как рисовать на виджете?
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 08.09.22 13:35
Оценка:
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, RussianFellow, Вы писали:


RF>>Есть некоторая таблица myTable типа QTableWidget. И в её клетках я хочу программно нарисовать какие-то рисунки. Как мне это сделать?

I>Берешь картинки и кладешь их в ресурсы, берешь QLabel устанавливаешь ему setPixmap

А если мне не нужно создавать ресурсы с картинками, а рисовать, допустим, прямоугольник с большей или меньшей шириной (в зависимости от условия в программе)? Можно ли программно рисовать геометрические фигуры в QLabel? Если да, то как это сделать?
1613 г. = 2024 г.
Re[5]: Как рисовать на виджете?
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 08.09.22 13:57
Оценка:
Вот я нашёл:

class MyLabel : public QLabel
{
    Q_OBJECT
public: 
    MyLabel(QWidget *parent = nullptr) : QLabel(parent) {}
 
protected:
    void paintEvent(QPaintEvent *event) override
    {
        // ваш код
    }
}

Затем в дизайнере преобразуете QLabel в MyLabel.


https://www.cyberforum.ru/qt/thread1967196.html
1613 г. = 2024 г.
Re[6]: Как рисовать на виджете?
От: Igore Россия  
Дата: 08.09.22 14:32
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Вот я нашёл:

RF>https://www.cyberforum.ru/qt/thread1967196.html
Да чтож ты всё ручками рисовать то хочешь

RF>А если мне не нужно создавать ресурсы с картинками, а рисовать, допустим, прямоугольник с большей или меньшей шириной (в зависимости от условия в программе)?

Берешь виджет, внутрь него помещаешь еще один виджет, выставляешь ему ширину, цвет и всё, а этот отдельный виджет помещаешь в ячейку
rootWidget
-rectangleWidget
а уж как внутренний виджет разположен в Layout или еще как чтобы размеры при resize нормально сделать это уже от нужного поведения зависит
Re[5]: Как рисовать на виджете?
От: Igore Россия  
Дата: 09.09.22 07:59
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>А если мне не нужно создавать ресурсы с картинками, а рисовать, допустим, прямоугольник с большей или меньшей шириной (в зависимости от условия в программе)? Можно ли программно рисовать геометрические фигуры в QLabel? Если да, то как это сделать?


Еще подумалось, перейти всё таки на QTableView, а в модели через Qt::BackgroundRole возвращать QBrush с градиентом или трансформацией которая нужна
Re[2]: Как рисовать на виджете?
От: AlexGin Беларусь  
Дата: 10.09.22 08:34
Оценка:
Здравствуйте, alpha21264, Вы писали:

A>Не ругайтесь на новичка. Рисовать через вызов события — это действительно неочевидно.


Так нужно разжевать суть:
Когда окно (виджет) становится видимым для пользователя
графическая подсистема (надстройка над OS — неважно Windows, Linux) вызывает в нашем приложении событие отрисовки (paintEvent).
В обработчике этого события — рисуем всё, что требуется видеть пользователю в нашем окне (виджете).

P.S. Если быть предельно точным — сказанное относится и к MFC, и к Qt.
Несмотря на то, раелизация (в "кишках" фреймворка Qt или в том же MFC) будет всё-таки различной.
Отредактировано 11.09.2022 7:25 AlexGin . Предыдущая версия . Еще …
Отредактировано 10.09.2022 8:50 AlexGin . Предыдущая версия .
Отредактировано 10.09.2022 8:40 AlexGin . Предыдущая версия .
Отредактировано 10.09.2022 8:36 AlexGin . Предыдущая версия .
Re[4]: Как рисовать на виджете?
От: AlexGin Беларусь  
Дата: 10.09.22 08:47
Оценка: -1
Здравствуйте, alpha21264, Вы писали:

A>И... Я подозреваю, что там другие события.


Если мы говорим об MFC, то там за события отвечает Windows API.
Для Qt — OpenGL.

Для прикладного программиста — это то, от чего (для простой отрисовки) можно абстрагироваться.
Re[5]: Как рисовать на виджете?
От: DiPaolo Россия  
Дата: 10.09.22 09:53
Оценка: +1
RF>А если мне не нужно создавать ресурсы с картинками, а рисовать, допустим, прямоугольник с большей или меньшей шириной (в зависимости от условия в программе)? Можно ли программно рисовать геометрические фигуры в QLabel? Если да, то как это сделать?

Тут уже отвечали же на этот твой вопрос.

Ты прогресс бар, я так понимаю, хочешь рисовать? Тогда вставляй QProgressBar (https://doc.qt.io/qt-6/qprogressbar.html) в качестве виджета в айтем таблицы (https://doc.qt.io/qt-6/qtablewidget.html#setCellWidget).
Патриот здравого смысла
Re[5]: Как рисовать на виджете?
От: Shtole  
Дата: 10.09.22 11:27
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Вот код (рисование прямоугольника):


RF>
RF>QWidget *myWidget;

RF>// ...

RF>QPainter* myPainter = new QPainter(myWidget);
RF>myPainter->begin(myWidget);
RF>myPainter->setRenderHint(QPainter::Antialiasing);
RF>myPainter->setBrush(QColor(255,255,255));
RF>myPainter->drawRect(0,0,wyWidget->width(),myWidget->height());
RF>myPainter->end();
RF>


RF>В этом коде всё правильно?


Как сказал Лев Толстой, все контексты устройств похожи друг на друга.
Do you want to develop an app?
Re[3]: Как рисовать на виджете?
От: SaZ  
Дата: 12.09.22 12:32
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>...

RF>Есть некоторая таблица myTable типа QTableWidget. И в её клетках я хочу программно нарисовать какие-то рисунки. Как мне это сделать?

Вот я когда-то писал делегат для рисования в ячейках. В делегате есть QPainter — с ним можно уже делать что хочешь.
https://stackoverflow.com/a/16301316/1035613
Re: Как рисовать на виджете?
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 07.10.22 11:22
Оценка:
Рисование в клетке таблицы у меня работает. Для этого я создал класс QMyWidget, являющийся потомком класса QWidget, и класс QMyTableWidget, являющийся потомком класса QTableWidget. В этих двух классах я переопределил методы paintEvent.
Вот код:

struct  cellinfo
{
    int  cellstate;
    int  beginpos;
    int  endpos;
    bool isHighLine;
};

class  QMyWidget : public QWidget
{
    Q_OBJECT
public:
    QMyWidget(QWidget* parent=0, Qt::WindowFlags f=0);
    ~QMyWidget();
    cellinfo  mycellinfo;
protected:
    void  paintEvent(QPaintEvent *);
};

void  QMyWidget::paintEvent(QPaintEvent *e)
{
    QRect  rect, rect2;
    QBrush *pBrush;

    QWidget::paintEvent(e);
    resize(40, 30);
    QPainter  painter(this);
    rect = this->rect();
    pBrush = new QBrush(QColor(128,128,128));
    if (mycellinfo.cellstate==1)
    {
        rect2.setTop(rect.top()-2);
        rect2.setBottom(rect.bottom()-1);
        rect2.setLeft(rect.left+mycellinfo.beginpos);
        rect2.setRight(rect.right());
        painter.fillRect(rect2,*pBrush);
    }
    if (mycellinfo.cellstate==2)
    {
        rect2.setTop(rect.top()-2);
        rect2.setLeft(rect.left());
        rect2.setRight(rect.right());
        rect2.setBottom(rect.bottom()-1);
        painter.fillRect(rect2,*pBrush);
    }
    if (mycellinfo.cellstate==3)
    {
        rect2.setTop(rect.top()-2);
        rect2.setBottom(rect.bottom()-1);
        rect2.setLeft(rect.left());
        rect2.setRight(rect.left()+mycellinfo.endpos);
        painter.fillRect(rect2,*pBrush);
    }
    if (mycellinfo.cellstate==4)
    {
        rect2.setTop(rect.top()-2);
        rect2.setBottom(rect.bottom()-1);
        rect2.setLeft(rect.left+mycellinfo.beginpos);
        rect2.setRight(rect.left()+mycellinfo.endpos);
        painter.fillRect(rect2,*pBrush);
    }
}

class  QMyTableWidget : public QTableWidget
{
public:
    explicit QMyTableWidget(QWidget *parent=nullptr);
    QMyTableWidget(int rows, int columns, QWidget *parent=nullptr);
    std::vector<cellinfo>  cellattributes;
    // . . .
protected:
    void  paintEvent(QPaintEvent *);
}

void  QMyTableWidget::paintEvent(QPaintEvent *e)
{
    int  i, n, rowcount;
    QMyWidget* wgt;
    QPainter  painter(this);
    cellinfo  mycellinfo;
    QBrush *pBrush;

    QTableWidget::paintEvent(e);
    pBrush = new QBrush(QColor(128,128,128));
    rowcount = rowCount();
    if (rowcount>0)
    {
        for (n=0; n<rowcount; n++)
        {
            // . . .
            for (i=1; i<=24; i++)
            {
                mycellinfo = (cellinfo)(cellattributes.at(n*25+i));
                if (mycellinfo.cellstate!=0)
                {
                    wgt = new QMyWidget();
                    wgt->mycellinfo.cellstate = mycellinfo.cellstate;
                    wgt->mycellinfo.beginpos = mycellinfo.beginpos;
                    wgt->mycellinfo.endpos = mycellinfo.endpos;
                    wgt->mycellinfo.isHighLine = mycellinfo.isHighLine;
                    wgt->repaint();
                    this->setCellWidget(n,i,wgt);
                }
            }
        }
    }
}

В результате у меня всё работает!
1613 г. = 2024 г.
Re[2]: Как рисовать на виджете?
От: Нomunculus Россия  
Дата: 07.10.22 11:25
Оценка:
Здравствуйте, RussianFellow, Вы писали:

Здорово! Молодец!
Но все же лучше рисование отдельного виджета запихнуть в картинку и выводить уже картинку, и ее обновлять когда надо, а не каждый раз фигачить рисование с нуля.
Просто если у тебя будет таблица с миллионом ячеек и каждая будет себя отрисовывать — то все сдохнет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.