Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Нарисовать фигуру в label по нажатию кнопки
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Система рисования. Печать
zuze
Мне надо нарисовать фигуру в label по нажатию кнопки. В данном примере пытаюсь нарисовать эллипс.

Я делал так:

ldialog.h

#ifndef LDIALOG_H
#define LDIALOG_H

#include <QDialog>
#include <QPainter>

namespace Ui {
    class ldialog;
}

class ldialog : public QDialog
{
    Q_OBJECT

public:
    explicit ldialog(QWidget *parent = 0);
    ~ldialog();

public slots:
    void onClick();
    void MyDrawEllipse();

private:
    Ui::ldialog *ui;

};

#endif // LDIALOG_H


ldialog.cpp

#include "ldialog.h"
#include "ui_ldialog.h"

ldialog::ldialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ldialog)
{
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(onClick()));

}

ldialog::~ldialog()
{
    delete ui;
}
void ldialog::MyDrawEllipse()
{
        QPainter Ellipse1(ui->label);
        Ellipse1.setBrush(QBrush(Qt::black));
        Ellipse1.drawEllipse(10, 10, 600, 600);
}
void ldialog::onClick()
{
   ui->label->update();
}


main.cpp

#include <QtGui/QApplication>
#include "ldialog.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ldialog w;
    w.show();

    return a.exec();
}


Но после нажатию на кнопку эллипс не рисуется. Что я сделал не так?
RazrFalcon
Нужно наследоваться от QLabel и предопределить функцию paintEvent(), и уже в ней рисовать.

Пример.
zuze
RazrFalcon, большое спасибо, но чего-то не отображется всё равно, пока хочу сделать без нажатия на кннопку. То есть что бы при запуске программы, эллипс рисовался на label.

Сделал так:

ldialog.h

#ifndef LDIALOG_H
#define LDIALOG_H

#include <QDialog>
#include "l.h"

namespace Ui {
    class ldialog;
}

class ldialog : public QDialog
{
    Q_OBJECT

public:
    explicit ldialog(QWidget *parent = 0);
    ~ldialog();

private:
    Ui::ldialog *ui;

};

#endif // LDIALOG_H


ldialog.cpp

#include "ldialog.h"
#include "ui_ldialog.h"

ldialog::ldialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ldialog)
{
    ui->setupUi(this);
}

ldialog::~ldialog()
{
    delete ui;
}


l.h

#ifndef L_H
#define L_H

#include <QLabel>
#include <QPainter>

class l : public QLabel
{
    Q_OBJECT
public:
    explicit l(QWidget *parent = 0);

signals:

public slots:

protected:
    void paintEvent(QPaintEvent *event);

};

#endif // L_H


l.cpp

#include "l.h"

locator::l(QWidget *parent) :
    QLabel(parent)
{
}
// Ввывод окружности
void l::paintEvent(QPaintEvent *event)
{
    QLabel::paintEvent(event);
    QPainter Ellipse(this);
    Ellipse.setBrush(QBrush(Qt::black));
    Ellipse.drawEllipse(10, 10, 600, 600);
}


main.cpp

#include <QtGui/QApplication>
#include "ldialog.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ldialog w;
    w.show();

    return a.exec();
}


Что же опять не так?
zuze
Как я понял я не вызвал paintEvent(). Я пытался его вызвать в конструкторе находящегося в файле ldialog.cpp. Но ни чего почему-то не вывелось?

Пробовал сделать так:


update();


Также пробовал:

this->update();
zuze
Тот же самый код я попробовал написать в конструкторе находящегося в файле l.cpp. Но ни чего почему-то не вывелось. А если в конструкторе в файле main.cpp добавить

l l1;
l1.show();


То рядом с открывшейся программой откроется ещё одна программа где будет только label и там эллипс отображается.
Но это не то что мне нужно, значит, где-то я ещё ошибся?
RazrFalcon
А где в первом варианте вы предопределяете QLabel в интерефейсе?
ldialog::ldialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ldialog)
{
    ui->setupUi(this);
}
На форму вы новый QLabel добавили?
Он должен быть отнаследован от созданного вами класса.
Так как код рисования верный. Просто сам виджет вы не используете.
zuze
Цитата(RazrFalcon @ 9.11.2012, 20:50) *
А где в первом варианте вы предопределяете QLabel в интерефейсе?


К сожалению я не догадался это сделать.

Цитата(RazrFalcon @ 9.11.2012, 20:50) *
На форму вы новый QLabel добавили?


Нет, не добавлял, у меня на форме один QLabel.

Как я понял надо сделать QLabel от класса l? Сейчас надо подумать как это сделать.
Litkevich Yuriy
zuze, не стал читать всю тему.
У тебя по нажатии кнопки вызывается:
ui->label->update();
И зачем? Где вызов процедуры рисования?


Таки прочитал
Цитата(zuze @ 10.11.2012, 9:07) *
Как я понял надо сделать QLabel от класса l? Сейчас надо подумать как это сделать.
В Дизайнере щёлкнуть по твой метке (QLabel), правой кнопкой мыши -> "Унаследованные виджеты" (Promote to) и ввести информацию о твоём наследнике.
zuze
Litkevich Yuriy, я пока решил хотя бы нарисовать эллипс, без нажатия, то есть сразу как запускается программа.
В конструкторе находящегося в файле ldialog.cpp добавил Ваш код вызова.

ldialog::ldialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ldialog)
{
    ui->setupUi(this);
    ui->label->update();
}


Но почему-то эллипс не нарисовался?

Цитата(Litkevich Yuriy @ 10.11.2012, 8:48) *
В Дизайнере щёлкнуть по твой метке (QLabel), правой кнопкой мыши -> "Унаследованные виджеты" (Promote to) и ввести информацию о твоём наследнике.


Я попытался так сделать, но в окне это-го пункта не оказалось. Привожу скриншот окна.


Скриншот окна:


Litkevich Yuriy
Цитата(zuze @ 10.11.2012, 11:04) *
добавил Ваш код вызова.
это не мой код, это твой. Я его просто процитировал.

Цитата(zuze @ 10.11.2012, 11:04) *
Я попытался так сделать, но в окне это-го пункта не оказалось. Привожу скриншот окна.
Преобразовать в ...


вообще правильный путь для решения данной задачи:
Использовать один из классов (QImage, QPixmap) на нём рисуем с помощью рисовальщика (QPainter), тогда, когда нам это удобнее. Затем полученный рисунок устанавливаем в качестве изображения метки (QLabel::setPixmap()).
zuze
Litkevich Yuriy, большое спасибо. Я сделал В Дизайнере щёлкнуть по твой метке (QLabel), правой кнопкой мыши ->"Преобразовать в ..." (Promote to) и указал там класс l. После этого эллипс стал выводиться на label и даже не надо прописывать

ui->label->update();


Теперь вся загвоздка в том чтобы рисовался эллипс по нажатию кнопки.
Я пробовал так:

В файле ldialog.cpp

void ldialog::onClick()
{
    ui->label->update();
}


А в конструкторе прописал

connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(onClick()));


А в файл ldialog.h добавил:

public slots:
    void onClick();


Это может и сработало бы, если бы автоматически эллипс не рисовался. Но в данном случае это не подходит, так как эллипс рисуется без всякого запуск update().

1. Что же делать?
2. И если можно расскажите пожалуйста назначение действия "В Дизайнере щёлкнуть по твой метке (QLabel), правой кнопкой мыши ->"Преобразовать в ..." (Promote to) и указал там класс l"?
Litkevich Yuriy
Цитата(zuze @ 10.11.2012, 17:04) *
Я пробовал так:

Цитата(zuze @ 10.11.2012, 17:04) *
так как эллипс рисуется без всякого запуск update().
что ты ожидаешь от метода update()?


Цитата(zuze @ 10.11.2012, 17:04) *
2. И если можно расскажите пожалуйста назначение действия "В Дизайнере щёлкнуть по твой метке (QLabel), правой кнопкой мыши ->"Преобразовать в ..." (Promote to) и указал там класс l"?
Просто дизайнер будет создавать ui-файл, в котором вместо виджета типа Х упоминается его наследник. А во время дизайна (для наглядности) используется базовый класс.
zuze
Цитата(Litkevich Yuriy @ 11.11.2012, 5:07) *
что ты ожидаешь от метода update()?


Как я понял update() помечает элемент, как требующий перерисовки. А я думал, что он будет отключать автоматическое рисование на элементе и позволит нарисовать, только при нажатии кнопки.

Что тогда надо сделать, что бы заработало у меня?
zuze
Как я понял, чтобы рисовалось по нажатию кнопки надо сделать так было:

1. в файле l.h добавить

public:
    bool FlagDraw;


2. В файле l.cpp добавить в конструктор

FlagDraw = false;


3. В файле l.cpp изменить метод paintEvent(QPaintEvent *)

void locator::paintEvent(QPaintEvent *)
{
    if (FlagDraw == false)
    {
        QPainter Ellipse(this);
        Ellipse.setBrush(QBrush(Qt::black));
        Ellipse.drawEllipse(0, 0, 600, 600);
    }
}


4. В файле ldialog.cpp изменить метод onClick()

void locatordialog::onClick()
{
    FlagDraw = true;
    if (FlagDraw == true)
     ui->label->update();
}


Но так как в этом классе переменная FlagDraw не видна пытался добавить в файл ldialog.h

public:
    friend class l;


Но это не помогло, что можно придумать, что бы FlagDraw была видна в классе ldialog или вообще как-то иначе надо было делать?

Прошу прощения в посте в место класса ldialog я случайно написал locatordialog, а в место класса l я случайно написал locator. Сам поправить свой пост не мог, так как почем-то нет таких прав, даже профиль не могу свой изменить, хотя авторизацию на форуме прошёл. Писал в администрацию форума, но она мне не ответила.
Litkevich Yuriy
Цитата(zuze @ 11.11.2012, 10:17) *
Как я понял update() помечает элемент, как требующий перерисовки.
только пометка о необходимости принудительно перерисовать виджет (вызвать его метод repaint()). Обычно перерисовка происходит при изменении размеров виджета. А вот когда происходит изменение его содержимого, программист должен сам вызвать этот метод.


Цитата(zuze @ 11.11.2012, 12:41) *
Что тогда надо сделать, что бы заработало у меня?
Цитата(Litkevich Yuriy @ 10.11.2012, 16:07) *
вообще правильный путь для решения данной задачи:
Использовать один из классов (QImage, QPixmap) на нём рисуем с помощью рисовальщика (QPainter), тогда, когда нам это удобнее. Затем полученный рисунок устанавливаем в качестве изображения метки (QLabel::setPixmap()).
zuze
Litkevich Yuriy, я так понял, что бы FlagDraw была видна в классе ldialog, то нужно передать с помощью Сигнала её. Не могли бы Вы рассказать как правильно это сделать?
zuze
Задача решена. У меня заработало. Выкладываю, может кому пригодиться.

1. Создаём проект GUI
2. В дизайнере выставляем label и pushButton на форуму окна программы
3. Создаём произвольный класс от класса QLabel

#ifndef L_H
#define L_H

#include <QLabel>
#include <QPainter>

class l : public QLabel
{
    Q_OBJECT
public:
    explicit l(QWidget *parent = 0);
    bool FlagDraw;

signals:

public slots:

protected:
    void paintEvent(QPaintEvent *);

};
#endif // L_H


#include "l.h"

l::l(QWidget *parent) :
    QLabel(parent)
{
    FlagDraw = false;
}
// Вывод окружности
void l::paintEvent(QPaintEvent *)
{
    if (FlagDraw == true)
    {
        QPainter Ellipse(this);
        Ellipse.setBrush(QBrush(Qt::black));
        Ellipse.drawEllipse(0, 0, 600, 600);
    }
}


4. Класс при создании проекта имеет вид

#ifndef LDIALOG_H
#define LDIALOG_H
#include <QDialog>
#include "l.h"

namespace Ui {
    class ldialog;
}

class ldialog : public QDialog
{
    Q_OBJECT

public:
    explicit ldialog(QWidget *parent = 0);
    ~ldialog();

public slots:
    void onClick();

private:
    Ui::ldialog *ui;

};
#endif // LDIALOG_H


#include "ldialog.h"
#include "ui_ldialog.h"

ldialog::ldialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ldialog)
{
    ui->setupUi(this);

    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(onClick()));
}

ldialog::~ldialog()
{
    delete ui;
}
void ldialog::onClick()
{
     ui->label->FlagDraw = true;
     ui->label->update();
}


5. В Дизайнере щёлкнуть по метке Label, правой кнопкой мыши ->"Преобразовать в ..." (Promote to) и указал там класс l" и поставить галочку, там, где это будет предложено.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.