LINUX.ORG.RU

Помогите разобраться в QT джунглях.


0

1

Несколько часов выкуривания qt-шных манов и примеров вызвали локальный взрыв мозга и падение самооценки до отрицательных значений. А задача казалось бы простая. Создать в окошке поле, в котором можно чего-нибудь нарисовать. Появились пара вариантов. 1) Отнаследовать от QWidget что-нибудь свое.(А можно просто использовать готовый QLabel?) Определить там QPaintWidget, и с помощью Qpainter -а нарисовать то что нужно. Я только не понял как задать место расположения и габариты своего виджета 2) Сформировать изображение в QImage или QPixmap(какая между ними разница?),делая это с помощью ихних собсвенных setPixel-ов или бежать за помощью к Qpainter (опять таки, что лучше?) А потом отрисовать на своем виджете с помощью QPainter::drawImage

Как православно?И где можно найти sempl-ы реализующие второй вариант?

★★★

Последнее исправление: LIKAN (всего исправлений: 1)

Ответ на: комментарий от shty

Не, я хочу что-то вроде эмулятора консоли сделать, так что гоняться за курсором не буду....

LIKAN ★★★
() автор топика
Ответ на: комментарий от shty

Не очень понятно какую там роль играет paintEvent, и собственно разве не в нем нужно все эти точки отрисовывать?

LIKAN ★★★
() автор топика

Все варианты правильные =)

Отнаследовать от QWidget что-нибудь свое.

Да, прокатит. От виджета можно наследовать и в производном классе переопределит событие paintEvent. Внутри этого события создаётся QPainter p(this) и при помощи него что-то рисуется на виджете исходя из его текущей геометрии. Координаты задаются в системе координат самого виджета (отсчитываются от левого верхнего угла).

Если наследовать не от QWidget, а от какого-то другого виджета, например от QLabel или QFrame, то в обаботчике paintEvent нужно ещё будет вызвать соответствующую функцию родительского виджета QFrame::paintEvent(event);

Я только не понял как задать место расположения и габариты своего виджета

Смотря что хочется сделать. У Qt есть много функций, которые могут влиять на размер виджета. Основные: minimumSize, maximumSize, sizeHint и sizePolicy. Эти свойства могут использоваться для того чтобы размер и положение виджета вычислялось автоматически внутри лейаутов (QLayout).

Свойство geometry позволяет задать геометрию «жёстко». В понятие геометрии входит и размер и положение. Координаты задаются относительно родительского виджета.

Тем не менее задавать положение и размер виджета из самого виджета --- некий моветон. Это надо делать из кода, который этот виджет создаёт.

Сформировать изображение в QImage или QPixmap(какая между ними разница?)

Если изображение сложное или должно меняться рекомендую сразу посмотреть на QGraphicsScene и QGraphicsView. При желании можно унаследовать класс от QGraphicsView и запилить сцену прямо в нём.

Классы QImage/QPixmap/QBitmap/QPicture имеют схожие функции, но оптимизированы для разного применения.

QPixmap предназначен для хранения и отображения уже готовой картинки. QBitmap это фактически вариант QPixmap для картинок с 1-битной глубиной цвета.

QImage наследует от QPaintDevice. Он подходит для того чтобы создавать картинку с нуля (рисовать её) и для того, чтобы выводить её на экран и работать с отдельными пикселями.

QPicture записывает последовательность действий, произведённых с ним и потом применяет её к некоторому QPaintDevice. Этот класс подходит для преобразования уже имеющихся изображений «потоковым методом».

Правда при отрисовке всё равно QPainter или QGraphicsScene будут использоваться.

Вот как-то так.

ssvda
()
Ответ на: комментарий от ssvda

Спасибо, помогло. Но возникли ещё вопросы. Первое, как мой созданный виджет (Ну пусть MyWid) показывать уже на существующем окне, отнаследованном от QDialog. Второе, как к моему виджету приделать скроллбары.Я так понимаю, что это будет удобней делать ковыряясь в *.ui файле.(QtCreator) Только вот как им пользоваться я так и не понял. Как в коде обращаться к виджетам, понарисованым во встроенном редакторе? Если рисовать пустой виджет, а потом преобразовывать его к нужному типу мне IDE обещат мне сгенерить заголовочник, да вот в папке с проектом я его не вижу.............

LIKAN ★★★
() автор топика

Несколько часов выкуривания qt-шных манов

вообще-то там дофига примеров с кодом, в том числе на рисование всякой фигни

Harald ★★★★★
()
Ответ на: комментарий от LIKAN

Первое, как мой созданный виджет (Ну пусть MyWid) показывать уже на существующем окне

Уже ответили.

Второе, как к моему виджету приделать скроллбары

Если виджет должен быть со скролбаром, то я бы посоветовал его унаследовать от QScrollArea.

Только вот как им пользоваться я так и не понял. Как в коде обращаться к виджетам, понарисованым во встроенном редакторе? Если рисовать пустой виджет, а потом преобразовывать его к нужному типу мне IDE обещат мне сгенерить заголовочник, да вот в папке с проектом я его не вижу.............

Заголовочный файл появится во время компиляции проекта, к которому подключён .ui файл. Не важно завершится компиляция успехом или ошибкой: заголовочник тем не менее появится.

ssvda
()
Ответ на: комментарий от ssvda

Уже ответили.

Эмм, простите где? В тех двух ссылках информация по qt designer, ну и про использование *.ui файла. Как это осуществить с++ способом?

LIKAN ★★★
() автор топика
Ответ на: комментарий от LIKAN

QDialog *d = new QDialog();

d->setLayout(new QHBoxLayout);

QPushButton *b = new QPushButton(d);

d->layout()->addWidget(b);

QMyWdiget *w = new QMyWidget(d);

d->layout()->addWidget(w);

Вообще говоря QT4 программирование GUI на C++ / Жасмин Бланшет, Марк Саммерфилд. --- М.: «КУДИЦ-ПРЕСС», 2008, изд. второе настоятельно рекомендуется. Если не хочется покупать бумажную, то она есть на самом известном трекере россии и и ещё много где.

ssvda
()
Ответ на: комментарий от ssvda

Неа, не пашет. Если делаю просто d->show(); то никаких признаков наличия виджета *w-нет. Если делаю и d->show() и w->show(), то сначала получаю окно d, а w появляется только если закрыть окно d.

LIKAN ★★★
() автор топика
Ответ на: комментарий от LIKAN

Точней вторая ситуация если

d->show();
d->exec();
w->show();
Просто 2 show, выдают просто два окна.

LIKAN ★★★
() автор топика
Ответ на: комментарий от LIKAN

А кастомный виджет передаёт в конструкторе в базовый класс указатель на своего родителя?

class MyWidget
 :public QFrame
{
//...
public:
MyWidget(QWidget *parent = 0);
//...
};

//-------


MyWidget::MyWidget(QWidget *parent)
 :QFrame(parent)
{
//...
}
ssvda
()
Ответ на: комментарий от ssvda

Да вот в том-то и беда что все именно так, на это я в первую очередь внимание обратил. Посмотрите пожалуйста, может я что-то пропустил. http://pastebin.com/hS2kaEkQ ( родительский виджет) http://pastebin.com/dzPRRUKN (Второй виджет, который я должен отрисовать на первом) http://pastebin.com/AU2J7SLs (Ну и собственно main)

LIKAN ★★★
() автор топика
Ответ на: комментарий от LIKAN

Так оба виджета наследуют от QDialog. Я ещё не видел, чтобы один диалог встраивался в другой =)

По порядку:

(1) Зачем внутри диалога делать указатель на Ui::Dialog? Обычно от того, что создано uic'ом тупо наследуют. Но и этого недостаточно: в конструкторе нужно вызвать this->setupUi(this).

class Dialog : public QDialog, public Ui::Dialog
{
...
};

Dialog::Dialog(QWidget *parent = 0)
 :QDialog(parent)
{
 this->setupUi(this);
}

(2) В классе Dialog нафиг не нужно переопределять paintEvent. Он будет отрисовываться и отрисовывать виджет средствами Qt же.

(3) p->begin(this); Не вижу причин для этого. Почему просто не создавать каждый раз при перересовке новый Painter? Экономия мизерная.

(4) Ну и да, MyWidget надо наследовать от ВИДЖЕТА. Либо тупо от QWidget если всё будет делаться средствами только обработчика paintEvent, либо от виджета, предоставляющего подходящие функции. Например, если нужна рамка, то рационально использовать QFrame. Если нужны полосы прокрутки, то можно попробовать использовать QSrollArea.

Правда, куда проще просто сделать полноразмерный виджет и засунуть его потом в QSrollArea.

(5) w->show(); вообще убрать можно. А лучше даже нужно.

ssvda
()
Ответ на: комментарий от ssvda

Спасибо,с наследованием разобрался. Только по остальному вопросы остались. 1) paintEvent(). А где простите тогда рисовать(Если сказанная перед этим фраза - ересь,то будьте милосердны, QT курю второй день, в первый наткнулся на форум, где человека, который пытался рисовать вне paintEvent закидали палками) 2) Без w->show(); вообще ничего нет, даже признаков окошка, как без него? 3) MyWidget(теперь я его просто черным закрасил) проявляет свое существование только если окошко подвигать, paintEvent() я так понял себя проявляет, но все равно это как то неправильно...

LIKAN ★★★
() автор топика

Что, ЛОР уже не торт? Никто не ткнул носом ТС в Quick Time. А зря...

anonymous
()

Здесь уже написали, что QT - это Apple QuickTime, а интересующий ТСа инструмент называется Qt? :)

И да, присоединяюсь к рекомендации почитать книжку Б и С.

hobbit ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.