Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: sersar от Декабрь 03, 2008, 14:01



Название: Виджет
Отправлено: sersar от Декабрь 03, 2008, 14:01
Здравствуйте!

Мне необходимо создать вот такой виджет как у нод32 (файл вложен). Чтоб также за заголовок передвигался. Разместить элементы управления и т.д. Как это сделать?


Название: Re: Виджет
Отправлено: ритт от Декабрь 03, 2008, 14:04
и в чём, собственно, проблема?


Название: Re: Виджет
Отправлено: sersar от Декабрь 03, 2008, 14:29
и в чём, собственно, проблема?
Как это сделать? Можете план набросать? Вот то и то ???


Название: Re: Виджет
Отправлено: EhTemka от Декабрь 04, 2008, 12:51
Скачай книжицу какую-нибудь. например вот здесь

http://www.prog.org.ru/index.php?topic=765.msg29480#msg29480 (http://www.prog.org.ru/index.php?topic=765.msg29480#msg29480)

На первых парах поможет разобраться, что к чему и как виджеты создавать


Название: Re: Виджет
Отправлено: sersar от Декабрь 04, 2008, 13:37
Книга есть. На Qt уже писал и всё получалось. Мне нужен пример, чтоб понять принцип. Некому помочь :(


Название: Re: Виджет
Отправлено: EhTemka от Декабрь 04, 2008, 14:02
Ок. Завтра, сейчас времени нет.


Название: Re: Виджет
Отправлено: ритт от Декабрь 04, 2008, 14:11
дык, что именно понять?!

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


Название: Re: Виджет
Отправлено: sersar от Декабрь 04, 2008, 14:17
дык, что именно понять?!

нужно скруглённое окно? или серый тайтл? или тонкая кнопка закрытия?
пока только теряюсь в догадках что именно подсказать требуется...
Да. Вы правильно думаете. Ну немогу найти пример...
- скруглённое окно
- тонкая кнопка закрытия


Название: Re: Виджет
Отправлено: ритт от Декабрь 04, 2008, 14:31
т.к. за оформление окна отвечает оконный манагер (а на него воздействовать силой вряд ли получится), думаю, проще всего будет создать окно с отключенным оформлением (или рисовать на кране), наложить исключающую маску, установить лэйоут, разбивающий виджет на две части: заголовок и контент; заголовок снабдить иконкой и кнопкой закрытия + транслированием перемещения, если нужно...

читать документацию:
QWidget::setMask
QWidget::paintEvent
QPainter
Analog Clock Example
+
рыть код:
QMdiSubWindow
QWorkspace (опционально)

навскидку только это придумалось...


Название: Re: Виджет
Отправлено: EhTemka от Декабрь 09, 2008, 12:40
Цитировать
Да. Вы правильно думаете. Ну немогу найти пример...
- скруглённое окно
- тонкая кнопка закрытия

Наконец-то руки дошли :)
Ты наверно и сам уже разобрался, но вдруг другим понадобится

Воощем вот код виджета с самодельным заголовком

roundWidget.h

Код
C++ (Qt)
#ifndef ROUNDWIDGET_H
#define ROUNDWIDGET_H
 
#include <QWidget>
 
class QLabel;
class QToolButton;
class QVBoxLayout;
 
class RoundWidget : public QWidget
{
 
public:
RoundWidget(QWidget *content, QWidget *parent = 0, Qt::WindowFlags f = 0);
~RoundWidget();
 
// функция заголовочного текста и иконки
void setWidgetTitle(const QString &text, const QPixmap &pixmap = QPixmap());
 
// функция установки заливки загаловка
void setFillGradientTitle(const QColor &color1, const QColor &color2);
 
 
protected:
void resizeEvent(QResizeEvent *event);
bool eventFilter(QObject *obj, QEvent *event);
 
private:
QWidget *widgetTitle_;  // Заголовок окна
QLabel  *labelTitleIcon_;   // Иконка загаловка окна
QLabel  *labelTitleText_;   // Текст загаловка окна
QToolButton *btnClose_; // Кнопка закрытия окна
 
QPoint dragPosition_;
};
 
#endif // ROUNDWIDGET_H
 

roundWidget.cpp

Код
C++ (Qt)
#include "roundWidget.h"
#include <QLabel>
#include <QPixmap>
#include <QPainter>
#include <QBitmap>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSpacerItem>
#include <QApplication>
#include <QMouseEvent>
 
 
RoundWidget::RoundWidget(QWidget *content, QWidget *parent, Qt::WindowFlags flags)
: QWidget(parent, flags)
{
setMouseTracking(true);
 
QVBoxLayout *layoutWindow = new QVBoxLayout(this);
layoutWindow->setMargin(0);
layoutWindow->setSpacing(0);
layoutWindow->setAlignment(Qt::AlignTop);
 
// Создание заголовка окна
 
widgetTitle_ = new QWidget(this);
widgetTitle_->setAutoFillBackground(true);
widgetTitle_->setFixedHeight(16);
 
QHBoxLayout *layTitle = new QHBoxLayout(widgetTitle_);
layTitle->setMargin(2);
layTitle->setSpacing(0);
 
labelTitleIcon_ = new QLabel(widgetTitle_);
 
labelTitleText_ = new QLabel(widgetTitle_);
labelTitleText_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
labelTitleText_->setMouseTracking(true);
labelTitleText_->installEventFilter(this);
 
QPushButton *btnClose = new QPushButton(widgetTitle_);
btnClose->setFixedSize(8,8);
btnClose->setIcon(QIcon(QApplication::applicationDirPath() + "/close.png"));
// close.png - нарисованный в фотошопе крестик с прозрачным фоном
 
layTitle->addWidget(labelTitleIcon_);
layTitle->addWidget(labelTitleText_);
layTitle->addWidget(btnClose);
 
bool connectSS = false;  // test connection SIGNAL - SLOT
connectSS = connect(btnClose, SIGNAL(clicked()), this, SLOT(close())); // закрытие окна по нашей кнопке  
Q_ASSERT(connectSS);
 
layoutWindow->addWidget(widgetTitle_);
 
if (content) {  // виджет содержимого окна
layoutWindow->addWidget(content);
}
 
resize(minimumSizeHint());
}
 
RoundWidget::~RoundWidget()
{
 
}
 
void RoundWidget::setWidgetTitle(const QString &text, const QPixmap &pixmap)
{
labelTitleText_->setText(text);
labelTitleIcon_->setPixmap(pixmap);
}
 
void RoundWidget::setFillGradientTitle(const QColor &color1, const QColor &color2)
{
QLinearGradient gradient(0, 0, 0, widgetTitle_->height());
gradient.setColorAt(0.0, color1);
gradient.setColorAt(1.0, color2);
 
QPalette pal = widgetTitle_->palette();
QBrush br = pal.brush(QPalette::Button);
pal.setBrush(QPalette::Window, QBrush(gradient));
pal.setBrush(QPalette::Button, color2);
 
widgetTitle_->setPalette(pal);
}
 
bool RoundWidget::eventFilter(QObject *obj, QEvent *event)
{
QMouseEvent *e = 0;
if (obj == labelTitleText_ && (e = dynamic_cast<QMouseEvent *>(event))) {
 
// перепещение окна
if (e->type() == QEvent::MouseButtonPress && e->button() == Qt::LeftButton) {
dragPosition_ = e->globalPos() - frameGeometry().topLeft();
e->accept();
} else if (e->type() == QEvent::MouseMove && (e->buttons() & Qt::LeftButton)) {
move(e->globalPos() - dragPosition_);
e->accept();
}
 
return true;
}
 
return QObject::eventFilter(obj, event);
}
 
 
void RoundWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
 
QRect r = rect();
 
// делаем маску с закругленными краями под размер окна
QPixmap pix(r.size());
pix.fill(Qt::transparent);
 
QPainter p(&pix);
p.setBrush(Qt::black);
p.drawRoundRect(r, 5, 5);
 
setMask(pix.mask());
}

main.cpp

#include <QApplication>
#include <QPushButton>
#include "roundWidget.h"


Код
C++ (Qt)
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QApplication::setStyle("Plastique");
 
QPushButton *content = new QPushButton();
content->setText("Button");
content->setFixedSize(500, 200);
 
RoundWidget rw(content);
rw.setWidgetTitle("Tram param param", QPixmap(QApplication::applicationDirPath() + "/ai.png").scaled(12,12));
rw.setFillGradientTitle(Qt::white, Qt::magenta);
//rw.setFixedSize(300, 200);
rw.show();
 
return a.exec();
}

Собственно суть в следующем.
1) Создание собственного заголовка окна (у меня в конструкторе)
Состоит из двух лайблов
labelTitleIcon_ - иконка окна
widgetTitle_    - имя окна

и кнопки закрытия
btnClose

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


2) Наложение маску на виджет

Это происходит в перегруженной функции
void RoundWidget::resizeEvent(QResizeEvent *event)
там все просто

3) Реализация перемещения окна

перегруженная функция
bool RoundWidget::eventFilter(QObject *obj, QEvent *event)
тут ловятся события мыши, которые происходят на лайбле с именем окна, и перемещяется окно на заданную позицию

Остальное для красоты  ;)

С деталями нужно поиграться, чтоб до ума довести 


Название: Re: Виджет
Отправлено: sersar от Декабрь 09, 2008, 13:36
EhTemka
Большое спасибо! Пример - лучше любого совета!


Название: Re: Виджет
Отправлено: EhTemka от Декабрь 09, 2008, 13:52
Пожался ;)
Самому интересно порой покопаться, когда время есть

Но ты сначала разберись, может тебе и не это нужно было  :)


Название: Re: Виджет
Отправлено: Firefox от Февраль 02, 2009, 14:16
подскажите как решить такую маленькую проблемку: мне надо на форме отобразить индикаторы(лампочки), которые срабатывают при нажатии кнопок. по свойствам для этого подходят CheckBox, но мне надо круглой формы или RadioButton но нужно чтоб была возможность включать нечколько лампочек сразу и в любых вариациях. ???


Название: Re: Виджет
Отправлено: spirit от Февраль 02, 2009, 14:31
юзайте QRadioButton только setAutoExclusive установите в false.


Название: Re: Виджет
Отправлено: Firefox от Февраль 02, 2009, 18:20
спасиб, я уже нашла правда, но тут другой вопрос возник, можете подсказать:у меня точка в радиобатане ставиться по нажатию кнопки, и как сделать так чтоб при нажатии мышкой(кликом) по радиобатану не менялось его состояние?тоесть ничего не происходило


Название: Re: Виджет
Отправлено: spirit от Февраль 02, 2009, 18:33
см. setCheckable


Название: Re: Виджет
Отправлено: lit-uriy от Февраль 02, 2009, 19:26
2 Firefox, лампочки лучше возьми здесь (http://www.qt-apps.org/index.php?xcontentmode=4298), и не мучай виджеты, у которых другое назначение.


Название: Re: Виджет
Отправлено: Firefox от Февраль 03, 2009, 15:13
спасибо всем


Название: Re: Виджет
Отправлено: AAXEE от Февраль 12, 2009, 21:29
Может переопределить mousePressEvent или mouseReleaseEvent?