PDA

View Full Version : Implementing a butcon



Theo Landman
26th July 2007, 09:34
We currently have a montage application on Windows which we want to have on Linux and Solaris as well. It has been decided that we are going to write the application from scratch using Qt. One of those "little" features that now have to be ported is a properties toolbar that allows the user to directly set things line text colour, line/edge colour, fill colour, line width and line type. If it is clicked a pane drops down from which the user can select the different kinds of line types. Is there a way to make something like this in Qt and if so what is the best approach to implement this? I assume that the solutions for the other butcons the solution is more or less the same.
http://www.justcroft.com/support/images/line-type-drop.png
Thanks in advance for any hints
Theo

marcel
26th July 2007, 09:43
I think the best way is to implement a custom widget consisting of 2 tool buttons - one is the actual tool button, the other is the button that activates the menu.
You will have a horizontal layout, in which you will put the 2 buttons. The drop down menu button should be fixed size and on click should remain toggled.

You could add various look&feel functionality, depending on what you need.

Regards

jpn
27th July 2007, 19:15
No need for two separate buttons :)

QToolButton::ToolButtonPopupMode (http://doc.trolltech.com/4.3/qtoolbutton.html#ToolButtonPopupMode-enum):


In this mode the tool button displays a special arrow to indicate that a menu is present. The menu is displayed when the arrow part of the button is pressed.


A custom widget can be easily added to a QMenu by wrapping it into a QWidgetAction. An example follows:


QToolButton* button = new QToolButton(this);
button->setPopupMode(QToolButton::MenuButtonPopup);
button->setIcon(QPixmap(":/trolltech/styles/commonstyle/images/viewdetailed-16.png"));

QMenu* menu = new QMenu(button);
QCalendarWidget* calendar = new QCalendarWidget(menu);
QWidgetAction* action = new QWidgetAction(menu);
action->setDefaultWidget(calendar);
menu->addAction(action);
button->setMenu(menu);

Theo Landman
1st August 2007, 13:52
Thanks for the various hints.
I ended up sub-classing QMenu and then implemented my own paintEvent():


void
JQLineTypeMenu::paintEvent(
QPaintEvent* event
)
{
QPainter p(this);
QRegion emptyArea = QRegion(rect());

//draw the items that need updating..
foreach ( QAction* action, actions() )
{
QRect adjustedActionRect = actionGeometry(action);
if ( !event->rect().intersects(adjustedActionRect) )
continue;

//set the clip region to be extra safe (and adjust for the scrollers)
QRegion adjustedActionReg(adjustedActionRect);
emptyArea -= adjustedActionReg;
p.setClipRegion(adjustedActionReg);

QStyleOptionMenuItem opt;
initStyleOption(&opt, action);
opt.rect = adjustedActionRect;
drawMenuItem(&opt, &p, action);
}
...
}
void
JQLineTypeMenu::drawMenuItem(
const QStyleOptionMenuItem* opt,
QPainter* p,
const QAction* action
)
{
bool act = opt->state & QStyle::State_Selected;
QBrush fill = opt->palette.brush(act ? QPalette::Highlight : QPalette::Button);
p->fillRect(opt->rect, fill);

QPen linePen(static_cast<Qt::PenStyle>(action->data().toInt()));
linePen.setWidth(3);
linePen.setBrush(opt->palette.brush(act ? QPalette::HighlightedText : QPalette::ButtonText));
p->setPen(linePen);
p->drawLine(opt->rect.left(), opt->rect.center().y(), opt->rect.right(), opt->rect.center().y());
}

The various actions in the menu held the different pen styles (using QAction::setData()). I then instanced my JQLineTypeMenu for the toolbar.
Note: if you need also the scrollbar and/or tear-off support then it is better creating a custom QWidget and insert instances of those in the menu through QActionWidget.
The whole Qt library is full of private data members that sometimes makes C++ deriving a big cut&paste exercise :mad:

jpn
6th August 2007, 20:21
The whole Qt library is full of private data members that sometimes makes C++ deriving a big cut&paste exercise :mad:
That's unfortunate but (in most parts of the library) still essential for TT to retain binary compatibility (http://trolltech.com/developer/knowledgebase/560). TT is always open for suggestions (http://trolltech.com/developer/task-tracker) when it comes to improvements of any kind, like adding new methods to ease up a common (and sensible) task or so. ;)