Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: daimon от Май 16, 2011, 00:04



Название: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 00:04
Как программно скрыть скролл и кнопки на виджете списка?
Идея такая - чтобы не долбать мозги с виджетом легенды для графика, я хочу создать объект виджета спискаи его настроить под легенду и скрыть скролл и кнопки. При нахождении курсора мыши на виджете кнопки и скролл появляются, если вне - снова исчезают. При этом список висит на виджете и он полностью рабочий. Было бы круто потом делать граб большого виджета со списком и там бы не было даже заметно, что присутствует лист виджет.
спс


Название: Re: Настройка QListWidget
Отправлено: GreatSnake от Май 16, 2011, 09:04
void   QAbstractScrollArea::setVerticalScrollBarPolicy ( Qt::ScrollBarPolicy )
void   QAbstractScrollArea::setHorizontalScrollBarPolicy ( Qt::ScrollBarPolicy )


Название: Re: Настройка QListWidget
Отправлено: daimon от Май 16, 2011, 13:33
void   QAbstractScrollArea::setVerticalScrollBarPolicy ( Qt::ScrollBarPolicy )
void   QAbstractScrollArea::setHorizontalScrollBarPolicy ( Qt::ScrollBarPolicy )
спс, а как заставить лист виджет открывать и скрывать скролы по наведению на него мыши?
 - пробовал с фокусом - нет (если лист виджет один на виджете, то он сразу в фокусе)
 - пробовал с координатами мыши - если локальные, то они уже не считываются при наведении мыши на лист виджет, так как там уже свои координаты относительно лист виджета, если глобальные - нет метода для лист виджета - глобальное положение

мне нужно как-то увидеть, что мышь наведена на лист виджет

спс


Название: Re: Настройка QListWidget
Отправлено: GreatSnake от Май 16, 2011, 13:41
Отнаследуйся от QListWidget и перегрузи event():
Код
C++ (Qt)
bool YourListWidget::event( QEvent *event )
{
switch( event->type() )
{
case QEvent::HoverEnter:
setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
break;
case QEvent::HoverLeave:
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
break;
default:
break;
}
return QListWidget::event( event );
}
 


Название: Re: Настройка QListWidget
Отправлено: daimon от Май 16, 2011, 14:14
Отнаследуйся от QListWidget и перегрузи event():
Код
C++ (Qt)
bool YourListWidget::event( QEvent *event )
{
switch( event->type() )
{
case QEvent::HoverEnter:
setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
break;
case QEvent::HoverLeave:
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
break;
default:
break;
}
return QListWidget::event( event );
}
 

сделал так
Код
C++ (Qt)
#include <QtGui>
 
class CListLegend: public QListWidget
{
Q_OBJECT
public:
CListLegend(QWidget *parent):QListWidget(parent)
{
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
bool event(QEvent * ev)
{
switch( ev->type() )
{
case QEvent::HoverEnter:
setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
break;
case QEvent::HoverLeave:
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
break;
default:
break;
}
return QListWidget::event( ev );
}
 
 
};
 
 

где использую добавил много итемов - не работает, дебажу - в евент моего типа заходит только типы евентов не те
что не так?
Код
C
list = new CListLegend (this);
list->move(10,10);
list->addItems(QStringList()<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf");


Название: Re: Настройка QListWidget
Отправлено: GreatSnake от Май 16, 2011, 14:21
Поменяй
HoverEnter на Enter
HoverLeave на Leave.


Название: Re: Настройка QListWidget
Отправлено: daimon от Май 16, 2011, 14:25
Поменяй
HoverEnter на Enter
HoverLeave на Leave.
чётко, спс
буду дальше думу делать


Название: Re: Настройка QListWidget
Отправлено: daimon от Май 16, 2011, 14:58
так теперь не могу запретить выделение итемов

делаю так
Код
C++ (Qt)
CListLegend(QWidget *parent):QListWidget(parent)
{
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setSelectionMode(QAbstractItemView::SelectionMode::NoSelection);
blockSignals(true);
}
выделений уже нет, но всё равно остаётся рамка от выделенного итема.
как её убрать?


Название: Re: Настройка QListWidget
Отправлено: daimon от Май 16, 2011, 15:09
есть метод какой-то setSelectionRectVisible(false), но как он работает не понятно
делал true во всех режимах выделения - толку нет


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: GreatSnake от Май 16, 2011, 15:19
Пора бы уже научиться работать с ассистентом :)
Чтобы понять, что может делать определенный класс, идёшь по ссылке List of all members, including inherited members (почти в самом начале описания) и внимательно всё изучаешь.

Цитировать
так теперь не могу запретить выделение итемов
setSelectionMode( QAbstractItemView::NoSelection )


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 15:21
Пора бы уже научиться работать с ассистентом :)
Чтобы понять, что может делать определенный класс, идёшь по ссылке List of all members, including inherited members (почти в самом начале описания) и внимательно всё изучаешь.

Цитировать
так теперь не могу запретить выделение итемов
setSelectionMode( QAbstractItemView::NoSelection )
выделений нет - рамка есть, я не зря пишу про рамку


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: GreatSnake от Май 16, 2011, 15:24
setFocusPolicy( Qt::NoFocus );


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 15:28
setFocusPolicy( Qt::NoFocus );

такую комбинацию я даже и придумать не мог
всё заработало, спс


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 15:53
Что посоветуете для такого варианта:
есть виджет графика - пеинтом рисую на пиксмепе всё для графика (renderPixmap(Settings2dGraph set), а потом этот пиксмеп рисую пеинт эвентом. При ресайзе идёт обновление пиксмепа с изменёнными настройками - размер пиксмепа под размер виджета. Для записи графика в файл я возвращаю пиксмеп с нужным размеров извне и его сохраняю.
Так вот проблема такая, если я добавляю виджет списка легенды то в итоге в рендере пиксмепа не будет этого списка.
Или грабить виджет списка как пиксмеп и рисовать на пиксмепе - тогда получится, что сам виджет будет висеть на своём графическом виде (картинке) - как-то тупо получается.



Название: Re: Настройка QListWidget под легенду для графика
Отправлено: GreatSnake от Май 16, 2011, 16:12
Цитировать
есть виджет графика - пеинтом рисую на пиксмепе всё для графика (renderPixmap(Settings2dGraph set), а потом этот пиксмеп рисую пеинт эвентом. При ресайзе идёт обновление пиксмепа с изменёнными настройками - размер пиксмепа под размер виджета.
И зачем такой изврат?

Цитировать
Или грабить виджет списка как пиксмеп и рисовать на пиксмепе - тогда получится, что сам виджет будет висеть на своём графическом виде (картинке) - как-то тупо получается.
Ничего не понял.


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 16:21
есть виджет, который рисует график

что там происходит - для того, что каждый раз заново ничего не рисовать, я решил создать пиксмеп и его заполнить до пеинт эвента, а потом этот же пеинт эвент рисовать

отличия только, когда меняется размер виджета, тогда я перерисовую пиксмеп (renderPixmap(...) с новыми парметрами - размер пиксмепа

Код
C++ (Qt)
void CPlotter2d::paintEvent(QPaintEvent * /* event */)
{
   QStylePainter painter(this);
 
painter.drawPixmap(0, 0,pixmap);// mg);*/
//refreshPixmap(opt_graph);
 
}
 
void CPlotter2d::resizeEvent(QResizeEvent * /* event */)
{
 
opt_graph.width_widget = this->size().width();
opt_graph.height_widget = this->size().height();
 
pixmap= refreshPixmap(opt_graph);
 
//   refreshPixmap(opt_graph);
}

всё этот делал, чтобы уменьшить нагрузку на процессор - пиксмеп меняется только при ресайзе виджета

для реализации экспорта графика в файл как картинку, я использую функцию рендеринга того пиксмепа, только туда отправляю настройки этого пиксмепа - под размер картинки, которую хочу сохранить и на выходе получаю пиксмеп и его сохраняю.


Цитировать
Или грабить виджет списка как пиксмеп и рисовать на пиксмепе - тогда получится, что сам виджет будет висеть на своём графическом виде (картинке) - как-то тупо получается.
Ничего не понял.

сохраняется только то, что есть на пиксмепе, а именно нарисованные линии, оси и т.д.
если я повешу на виджет графика свой список легенду, то на пиксмепе его не будет и на картинке в итоге тоже

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


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: GreatSnake от Май 16, 2011, 16:29
Цитировать
всё этот делал, чтобы уменьшить нагрузку на процессор - пиксмеп меняется только при ресайзе виджета
Да уж "соптимиздил" :)
А если юзер захочет подогнать размер окна, то просядем? В Qt уже встроен double-buffering, так ты ещё и свой забацал?
А чем не устроил  QGraphicsView? Твой CListLegend в него встроился бы легко.


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 16:35
Цитировать
всё этот делал, чтобы уменьшить нагрузку на процессор - пиксмеп меняется только при ресайзе виджета
Да уж "соптимиздил" :)
А если юзер захочет подогнать размер окна, то просядем? В Qt уже встроен double-buffering, так ты ещё и свой забацал?
А чем не устроил  QGraphicsView? Твой CListLegend в него встроился бы легко.
ну а так бы каждый раз пеинт эвентом рисовался бы график - весь рендер каждый раз или я не прав?
мда тут бы ещё как-то бы проверить, чтобы второй раз не перерисовывать тоже самое - хитрую проверку бы сделать
QGraphicsView пока не юзал - не знаю, пояни на простом примере

Основа проста - действующий виджет и при этом в итоге граб на картинке (при ресайзе график меняется - оси растягиваются и график тоже без помощи скейла - всё перерисовывается с учётом размера виджета, получается и виджет списка тоже надо двигать)


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: GreatSnake от Май 16, 2011, 16:39
Мде, в общем изобрёл очередной велосипед.
Почитай книжки насчёт QGraphicsView/QGraphicsScene.
Всё уже давно сделано.


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 16:41
Код
C++ (Qt)
void CPlotter2d::resizeEvent(QResizeEvent * /* event */)
{
if(opt_graph.width_widget !=  this->size().width() || opt_graph.height_widget != this->size().height() )
{
opt_graph.width_widget = this->size().width();
opt_graph.height_widget = this->size().height();
 
pixmap= refreshPixmap(opt_graph);
}
 
//   refreshPixmap(opt_graph);
}

в общем лишний раз рисовать вроде не должно - только, когда размер меняется


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 16:48
походу нужно типа создать сцену на неё повесить итемом график и легенду и потом уже там колдовать
ну а график всё равно нужно перерисовывать при ресайзе - скейлить не катит - надписи просто тогда будуть растягиваться или сжиматься


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 17:41
события и сигналы обрабатывает вью или сцена?
пример события - на легенде чекбоксом поставил галку или снял, график перерисовался (появилась кривая, исчезла)
и вообще как тогда связать виджет графика и виджет легенды сигналами и слотами?

создал бы слот на сигнал чекбокса, там бы по старому возвращал бы объект настроек из виджета графика, ему менял бы характеристику кривой - скрить кривую, потом повесил бы новую настройку на график и refreshPixmap. Связал бы коннектом





Название: Re: Настройка QListWidget под легенду для графика
Отправлено: m_ax от Май 16, 2011, 18:12
события и сигналы обрабатывает вью или сцена?
пример события - на легенде чекбоксом поставил галку или снял, график перерисовался (появилась кривая, исчезла)
и вообще как тогда связать виджет графика и виджет легенды сигналами и слотами?

создал бы слот на сигнал чекбокса, там бы по старому возвращал бы объект настроек из виджета графика, ему менял бы характеристику кривой - скрить кривую, потом повесил бы новую настройку на график и refreshPixmap. Связал бы коннектом

В LightPlot2D, например, легенда  - это отдельный виджет (не QListWidget) и связывается она непосредственно с самим Plotter'ом так: Plotter имеет указатель на легенду и в курсе что и когда с ней делать.

   


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 18:35
можете кинуть ссылку на проект QLightPlot2D


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: m_ax от Май 16, 2011, 18:48
Цитировать
можете кинуть ссылку на проект QLightPlot2D
А Вы не в курсе?

Сама либа здесь: http://code.google.com/p/lightplot2d/downloads/list
Полный виджет со всеми диалогами и настройками здесь: http://www.prog.org.ru/topic_10208_90.html

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


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 18:58
Цитировать
можете кинуть ссылку на проект QLightPlot2D
А Вы не в курсе?

Сама либа здесь: http://code.google.com/p/lightplot2d/downloads/list
Полный виджет со всеми диалогами и настройками здесь: http://www.prog.org.ru/topic_10208_90.html

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


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: m_ax от Май 16, 2011, 19:09
На мой взгляд, если и писать подобные вещи, то лучше сразу использовать QGraphycsScene/View


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 19:12
На мой взгляд, если и писать подобные вещи, то лучше сразу использовать QGraphycsScene/View

времени пока нет - сейчас вставляю в сцену 2 виджета - график и легенду
как их размесить нормально - лейауты были бы хороши, есть подобное там?

и почему-то картинка не сохраняется

Код
C++ (Qt)
#include "clistwidgetlegendgraph2d.h"
#include <QtGui/QApplication>
 
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene(QRect(0,0,640,480));
 
CListLegend list(0);
list.addItems(QStringList()<<"sfdsdfshhhhhhhhhhhhhhhhdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf"<<"sfdsdfsdf"<<"sdf");
 
scene.addWidget(&list);
scene.addWidget(new QPushButton("button",0));
 
 
QPixmap pixmap;
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
scene.render(&painter);
painter.end();
 
pixmap.save("scene.png");
 
QGraphicsView view(&scene);
view.show();
return a.exec();
}
 


Название: Re: Настройка QListWidget под легенду для графика
Отправлено: daimon от Май 16, 2011, 22:52
Код
C
#include <QtGui>
 
class CListLegend: public QListWidget
{
Q_OBJECT
public:
CListLegend(QWidget *parent):QListWidget(parent)
{
 
setSelectionMode(QAbstractItemView::SelectionMode::NoSelection);
setSelectionRectVisible(false);
 
setFocusPolicy( Qt::NoFocus );
setFrameShape(QFrame::Box);
 
QPixmap image(10,10);
resize(100,80);
image.fill(2);
 
addItem(image,"fffjjjjjjjjjjjjddddddddjjjjjjjjjjjjjjjj",Qt::CheckState::Unchecked);
addItem(image,"fffjjjjjjjjjjjjjjjjjjjjjjjjjjjj",Qt::CheckState::Unchecked);
addItem(image,"fffjjjjjjjjjjjjjjjjjjjjjjjjjjjj",Qt::CheckState::Unchecked);
addItem(image,"fffjjjjjjjjjjjjj",Qt::CheckState::Unchecked);
addItem(image,"fffjjjjjjjjjjjjjjj",Qt::CheckState::Unchecked);
addItem(image,"fffjjjjjjjjjjjjjjjj",Qt::CheckState::Unchecked);
addItem(image,"fffjjjjjjjjjjjjjjjjjjjjjjjjjjjj",Qt::CheckState::Unchecked);
 
}
void addItem(const QIcon& icon,  const QString& str, Qt::CheckState state = Qt::CheckState::Unchecked)
{
QListWidget::addItem(new QListWidgetItem(str));
// item(count()-1)->setCheckState(state);
}
bool event(QEvent * ev)
{
 
switch( ev->type() )
{
case QEvent::Enter:
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded);
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
QListWidget::update();
break;
case QEvent::Leave:
 
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
QListWidget::update();
 
 
break;
default:
break;
}
return QListWidget::event( ev );
}
QPixmap image()
{
return QPixmap().grabWidget(this);
}
 
 
};
при таком варианте почему-то бок при появлении горизонального скрола - не соответствует максимальному итему
пробовал и апдейты подаблять - не помагает.
Что не так делаю?