| Home | ![]() |
By subclassing QtPieMenu and reimplementing a few functions, a menu with a different shape can be provided, which better fits the needs of your application. The following example shows how to generate a hexagon shaped pie menu with a transparent center, by reimplementing only three functions: generateMask(), reposition() and paintEvent().

hexagonpie.h:
#ifndef HEXAGONPIE_H
#define HEXAGONPIE_H
#include <qtpiemenu.h>
#include <qcolor.h>
class HexagonPie : public QtPieMenu
{
Q_OBJECT
public:
HexagonPie(const QString &title = QString::null,
const QColor &color = QColor(),
QWidget *parent = 0, const char *name = 0);
protected:
void generateMask(QBitmap *mask);
void reposition();
void paintEvent(QPaintEvent *e);
private:
QColor col;
};
#endif
hexagonpie.cpp:
/*
This example demonstrates subclassing of QtPieMenu in order to
provide a different shape. It reimplements the functions
generateMask(), reposition() and paintEvent().
The basic shape is a hexagon.
*/
#include "hexagonpie.h"
#include <qobject.h>
#include <qpainter.h>
#include <qbitmap.h>
#include <qfontmetrics.h>
#include <math.h>
/*!
Constructs a hexagon pie menu. The \a title, \a parent and \a name
arguments are passed to QtPieMenu's constructor. \a color sets the
color of the pie menu. This color will also be used to draw the
pie item of any parent menu.
*/
HexagonPie::HexagonPie(const QString &title, const QColor &color,
QWidget *parent, const char *name)
: QtPieMenu(title, parent, name), col(color)
{
}
/*!
Draws a hexagon shape on \a mask.
*/
void HexagonPie::generateMask(QBitmap *mask)
{
QPainter p(mask);
p.setPen(Qt::color1);
p.setBrush(Qt::color1);
int x = pix.rect().center().x();
int y = pix.rect().center().y();
for (int i = 0; i < 6; ++i) {
double a = indexToAngle(i, 6, true);
double b = indexToAngle(i + 1, 6, true);
double ax = outerRadius() * cos(a);
double ay = - outerRadius() * sin(a);
double bx = outerRadius() * cos(b);
double by = - outerRadius() * sin(b);
double cx = innerRadius() * cos(a);
double cy = - innerRadius() * sin(a);
double dx = innerRadius() * cos(b);
double dy = - innerRadius() * sin(b);
QPointArray poly(4);
poly.setPoint(0, x + (int) ax, y + (int) ay);
poly.setPoint(1, x + (int) bx, y + (int) by);
poly.setPoint(2, x + (int) dx, y + (int) dy);
poly.setPoint(3, x + (int) cx, y + (int) cy);
p.drawPolygon(poly);
}
}
/*!
The hexagon shaped pie menu has a special rule for placement; we
want the sub menus to be positioned precisely next to the parent.
Since this hexagon piemenu has a fixed default size, we can do a
precise repositioning before the menu is shown.
*/
void HexagonPie::reposition()
{
if (!parent()->inherits("HexagonPie"))
return;
HexagonPie *parentPie = reinterpret_cast<HexagonPie *>(parent());
QPoint parentCenter = mapToGlobal(parentPie->pos());
if (parentPie->subMenuAt(0) == this) {
move(mapFromGlobal(QPoint(parentCenter.x(), parentCenter.y() - 128)));
} else if (parentPie->subMenuAt(1) == this) {
move(mapFromGlobal(QPoint(parentCenter.x() - 112, parentCenter.y() - 64)));
} else if (parentPie->subMenuAt(2) == this) {
move(mapFromGlobal(QPoint(parentCenter.x() - 112, parentCenter.y() + 64)));
} else if (parentPie->subMenuAt(3) == this) {
move(mapFromGlobal(QPoint(parentCenter.x(), parentCenter.y() + 128)));
} else if (parentPie->subMenuAt(4) == this) {
move(mapFromGlobal(QPoint(parentCenter.x() + 112, parentCenter.y() + 64)));
} else if (parentPie->subMenuAt(5) == this) {
move(mapFromGlobal(QPoint(parentCenter.x() + 112, parentCenter.y() - 64)));
}
}
/*!
Draws the hexagon shape, taking shading and highlighting into
consideration.
*/
void HexagonPie::paintEvent(QPaintEvent *)
{
QPainter p(&pix);
pix.fill();
QColorGroup cGroup = colorGroup();
int x = pix.rect().center().x();
int y = pix.rect().center().y();
// Draw the segments
QFontMetrics fm(font());
for (int i = 0; i < 6; ++i) {
p.setPen(black);
// Find the brush we should use for drawing the segments of
// the menu. Each segment has its own color.
QColor baseColor = col;
if (itemType(i) == SubMenu)
baseColor = ((HexagonPie *)subMenuAt(i))->col;
if (i == highlightedItem()) {
QColor tmp = white;
if (baseColor.isValid()) {
QColor merge((tmp.red()*3 + baseColor.red()*2)/5,
(tmp.green()*3 + baseColor.green()*2)/5,
(tmp.blue()*3 + baseColor.blue()*2)/5);
p.setBrush(QBrush(merge));
} else {
p.setBrush(QBrush(tmp));
}
} else {
QColor tmp = cGroup.background();
if (baseColor.isValid()) {
QColor merge((tmp.red()*3 + baseColor.red()*2)/5,
(tmp.green()*3 + baseColor.green()*2)/5,
(tmp.blue()*3 + baseColor.blue()*2)/5);
p.setBrush(QBrush(merge));
} else {
p.setBrush(QBrush(tmp));
}
}
// Draw the polygon
double a = indexToAngle(i, 6, true);
double b = indexToAngle(i + 1, 6, true);
double ax = outerRadius() * cos(a);
double ay = - outerRadius() * sin(a);
double bx = outerRadius() * cos(b);
double by = - outerRadius() * sin(b);
double cx = innerRadius() * cos(a);
double cy = - innerRadius() * sin(a);
double dx = innerRadius() * cos(b);
double dy = - innerRadius() * sin(b);
QPointArray pointArray(4);
pointArray.putPoints(0, 4,
x + (int) ax, y + (int) ay,
x + (int) bx, y + (int) by,
x + (int) dx, y + (int) dy,
x + (int) cx, y + (int) cy);
if (paletteBackgroundPixmap())
p.setBrush(QBrush(p.brush().color(), *paletteBackgroundPixmap()));
p.drawPolygon(pointArray);
if (!itemText(i).isEmpty()) {
QFont font = p.font();
if (i == highlightedItem()) {
p.setPen(white);
font.setBold(true);
} else {
p.setPen(cGroup.text());
font.setBold(false);
}
p.setFont(font);
// Draw the title text
QString t = itemText(i);
p.drawText((int) (x + (ax + bx + cx + dx) / 4 - fm.width(t) / 2),
(int) (y + (ay + by + cy + dy) / 4), t);
font.setBold(false);
p.setFont(font);
}
}
bitBlt(this, QPoint(0, 0), &pix, pix.rect(), CopyROP, false);
}
main.cpp:
#include "hexagonpie.h"
#include <qapplication.h>
#include <qtextedit.h>
class MyEditor : public QTextEdit
{
Q_OBJECT
public:
MyEditor()
{
// Create a pie menu with six submenus, and no action items.
pie = new HexagonPie("Root", black, this, "Root");
pie->insertItem(new HexagonPie("N", red, pie, "N"));
pie->insertItem(new HexagonPie("NW", green, pie, "NW"));
pie->insertItem(new HexagonPie("SW", blue, pie, "SW"));
pie->insertItem(new HexagonPie("S", yellow, pie, "S"));
pie->insertItem(new HexagonPie("SE", gray, pie, "SE"));
pie->insertItem(new HexagonPie("NE", cyan, pie, "NE"));
for (int i = 0; i < 6; ++i) {
HexagonPie *subPie = (HexagonPie *)pie->subMenuAt(i);
subPie->insertItem("A", this, SLOT(noop()));
subPie->insertItem("B", this, SLOT(noop()));
subPie->insertItem("C", this, SLOT(noop()));
subPie->insertItem("D", this, SLOT(noop()));
subPie->insertItem("E", this, SLOT(noop()));
subPie->insertItem("F", this, SLOT(noop()));
}
}
public slots:
void noop()
{
}
protected:
void contentsContextMenuEvent(QContextMenuEvent *e) {
pie->popup(e->globalPos());
}
private:
HexagonPie *pie;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyEditor editor;
app.setMainWidget(&editor);
editor.show();
return app.exec();
}
#include "main.moc"
hexagon.pro:
TEMPLATE = app INCLUDEPATH += . include(../../src/qtpiemenu.pri) # Input HEADERS += hexagonpie.h SOURCES += hexagonpie.cpp main.cpp CONFIG += debug
| Copyright © 2003-2006 Trolltech | Trademarks | Qt Solutions
|