PDA

View Full Version : Palette toolbar need help plz...



Radagast
28th July 2008, 14:00
Qt 4.4.0
I need to create a palette toolbar like CorelDRAW has. It can be expanded to show all the colors and minimized into one column/row. I've tried both ways, using QGridLayout and setting positions and sizes of all widgets manually but nothing works normally:confused:
Just copy this code into your IDE and u'll see:
PaletteToolbarButton.h


#ifndef PALETTETOOLBARBUTTON_H
#define PALETTETOOLBARBUTTON_H

#include <QFrame>

class PaletteToolbarButton : public QFrame
{
Q_OBJECT
public:
PaletteToolbarButton(const QColor& newcolor = Qt::white, QWidget *parent = 0, const QSize& size = QSize(20,20), bool select = false);
QColor color() const
{
return curColor;
}
bool isSelected() const
{
return selected;
}
public slots:
void setColor(const QColor&);
void setSelected(bool sel = true);
signals:
void clicked(const QColor&);
protected:
void paintEvent ( QPaintEvent * event );
void mousePressEvent ( QMouseEvent * event );
private:
QColor curColor;
bool selected;
};

#endif // PALETTETOOLBARBUTTON_H


PaletteToolbarButton.cpp


#include <QtGui>
#include "PaletteToolbarButton.h"

PaletteToolbarButton::PaletteToolbarButton(const QColor& newcolor, QWidget *parent, const QSize& size, bool select)
: QFrame(parent), selected(select)
{
newcolor.isValid()? curColor = newcolor : curColor = Qt::transparent;
setMinimumSize(size);
setMaximumSize(size);
}
void PaletteToolbarButton::setColor(const QColor& newcolor)
{
if (newcolor.isValid() && newcolor != curColor)
{
curColor = newcolor;
update ();
}
}
void PaletteToolbarButton::setSelected(bool sel)
{
selected = sel;
update();
}
void PaletteToolbarButton::paintEvent ( QPaintEvent * event )
{
if (selected)
setFrameStyle(QFrame::WinPanel | QFrame::Raised);
else setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
QFrame::paintEvent(event);
QPainter painter(this);
if (curColor == Qt::transparent)
{
painter.setBrush(Qt::white);
painter.setPen(Qt::black);
painter.drawRect(1,1,width()-3,height()-3);
painter.drawLine(1,1,width()-2,height()-2);
painter.drawLine(1,height()-2,width()-2,1);
}
else
{
painter.setBrush(curColor);
painter.setPen(Qt::NoPen);
painter.drawRect(2,2,width()-4,height()-4);
}
}
void PaletteToolbarButton::mousePressEvent ( QMouseEvent * event )
{
if (event->button() == Qt::LeftButton)
emit clicked(curColor);
}


PaletteToolbar.h


#ifndef PALETTETOOLBAR_H
#define PALETTETOOLBAR_H

#include <QToolBar>
#include "PaletteToolbarButton.h"

class QToolButton;
class PaletteToolbar : public QToolBar
{
Q_OBJECT
public:
PaletteToolbar(const QList<QColor>& colorList = QList<QColor>(), const QString& title = "Palette", QWidget* parent = 0);
void addColor(const QColor&, int before = -1);//-1 means "add after the last one"
void removeColor(const QColor&);
bool isExpanded() const
{return expanded;}
QColor color() const
{ return selButton->color(); }
public slots:
void setExpanded(bool);
void setSelColor(const QColor&);
signals:
void expands(bool);
void colorChosen(const QColor&);
private slots:
void arrangeButtons();
void expandButtonTriggered();
protected:
void resizeEvent ( QResizeEvent * event ) ;
private:
bool expanded;
bool arranging;
QList<PaletteToolbarButton*> buttonList;
PaletteToolbarButton* selButton;
QWidget* layoutWidget;
QToolButton* expandButton;
QToolButton* customizeButton;
};

#endif // PALETTETOOLBAR_H


PaletteToolbar.cpp


#include <QtGui>
#include "PaletteToolbar.h"
PaletteToolbar::PaletteToolbar(const QList<QColor>& colorList, const QString& title, QWidget* parent)
: QToolBar(title,parent), expanded(false), arranging(false)
{
setFloatable(false);
layoutWidget = new QWidget(this);
QAction* actExpand = new QAction(this);
expandButton = new QToolButton(layoutWidget);
expandButton->setDefaultAction(actExpand);
connect(actExpand, SIGNAL(triggered()), this, SLOT(expandButtonTriggered()));
addWidget(layoutWidget);
foreach(QColor color, colorList)
{
PaletteToolbarButton* newButton = new PaletteToolbarButton(color,layoutWidget);
buttonList.append(newButton);
connect(newButton,SIGNAL(clicked(const QColor&)),this,SLOT(setSelColor(const QColor&)));
}
expandButton->setMinimumSize(buttonList.first()->minimumSize());
expandButton->setMaximumSize(buttonList.first()->maximumSize());
if (buttonList.size()) selButton = buttonList.first();
}
void PaletteToolbar::addColor(const QColor&, int before)
{}
void PaletteToolbar::removeColor(const QColor&)
{}
void PaletteToolbar::setExpanded(bool newexp)
{
if (expanded != newexp)
{
expanded = newexp;
arrangeButtons();
emit expands(newexp);
}
}
void PaletteToolbar::setSelColor(const QColor& newcolor)
{
selButton->setSelected(false);
selButton = static_cast<PaletteToolbarButton*> (sender());
selButton->setSelected(true);
emit colorChosen(newcolor);
}
void PaletteToolbar::resizeEvent ( QResizeEvent * event )
{
QToolBar::resizeEvent(event);
if (!arranging)
arrangeButtons();
}
void PaletteToolbar::expandButtonTriggered()
{
if (expanded)
setExpanded(false);
else setExpanded(true);
}
void PaletteToolbar::arrangeButtons()
{
if (buttonList.size()!=0)
{
arranging = true;
delete layoutWidget->layout();
QGridLayout* grid = new QGridLayout;
grid->setSpacing(2);
int cellWidth = buttonList.first()->minimumWidth()+2;
int cellHeight = buttonList.first()->minimumHeight()+2;
bool vert = orientation()==Qt::Vertical;
switch(static_cast<QMainWindow*>(parentWidget())->toolBarArea(this))
{
case Qt::LeftToolBarArea:
expandButton->setArrowType(expanded? Qt::LeftArrow : Qt::RightArrow);
break;
case Qt::RightToolBarArea:
expandButton->setArrowType(expanded? Qt::RightArrow : Qt::LeftArrow);
break;
case Qt::BottomToolBarArea:
expandButton->setArrowType(expanded? Qt::DownArrow : Qt::UpArrow);
break;
case Qt::TopToolBarArea:
expandButton->setArrowType(expanded? Qt::UpArrow : Qt::DownArrow);
break;
}
int ButtonsInRow,ButtonsInCol;
if (!expanded)
{
if (vert)
{
ButtonsInRow = 1;
ButtonsInCol = height() / cellHeight;
}
else //horizontal
{
ButtonsInCol = 1;
ButtonsInRow = width() / cellWidth;
}
}
else //ToolBar is expanded
{
if (vert)
{
ButtonsInCol = height() / cellHeight;
ButtonsInRow = (buttonList.size() + 1) / ButtonsInCol;
if ((buttonList.size() + 1) % ButtonsInCol) ++ButtonsInRow;
}
else //horizontal
{
ButtonsInRow = width() / cellWidth;
ButtonsInCol = (buttonList.size() + 1) / ButtonsInRow;
if ((buttonList.size() + 1) % ButtonsInRow) ++ButtonsInCol;
}
}
int Row = 0,Col = 0,i=0;
foreach(PaletteToolbarButton* button,buttonList)
{
grid->addWidget(button,Row,Col);++i;
if (vert)
{
++Row;
if (Row >= ButtonsInCol - 1)
{
if (Col >= ButtonsInRow - 1)
{
break;
}
else
{
++Col;
Row = 0;
}
}
}
else //horizontal
{
++Col;
if (Col >= ButtonsInRow - 1)
{
if (Row >= ButtonsInCol - 1)
{
break;
}
else
{
++Row;
Col = 0;
}
}
}
}//foreach
grid->addWidget(expandButton,Row,Col);
layoutWidget->setLayout(grid);
arranging = false;
}//if (buttonList.size()!=0)
}


in the constructor of the class derived from QMainWindow:

QStringList names = QColor::colorNames();
QList<QColor> colorlist;
foreach(QString name, names)
{
colorlist.append(QColor(name));
}
palette = new PaletteToolbar(colorlist);
addToolBar(Qt::RightToolBarArea,palette);

thanks in advance!

wysota
28th July 2008, 14:02
Isn't it by any chance a double thread?

Do you really need it to be a toolbar per se?

Radagast
28th July 2008, 14:02
I've spent a WEEK trying dozens of approaches. And please don't propose to use QDockWidget as it has another appearance, I need QToolBar's child.THX

Radagast
28th July 2008, 14:05
wysota
I've put the whole code in the first time and it's the best I can do as I am new to Qt. I'm sure that when it is finished it will be a very useful widget for many people and also a good lesson of toolbars and layouts usage.

Radagast
28th July 2008, 14:08
here's the way to manage buttons manually, without layout, but it also doesn't work fine :(

void PaletteToolbar::arrangeButtons()
{
if (buttonList.size()!=0)
{
arranging = true;
foreach(PaletteToolbarButton* button, buttonList)
{
button->hide();
}
expandButton->hide();
int cellWidth = buttonList.first()->minimumWidth()+2;
int cellHeight = buttonList.first()->minimumHeight()+2;
int maxWidth = cellWidth, maxHeight = cellHeight;
bool vert = orientation()==Qt::Vertical;
switch(static_cast<QMainWindow*>(parentWidget())->toolBarArea(this))
{
case Qt::LeftToolBarArea:
expandButton->setArrowType(expanded? Qt::LeftArrow : Qt::RightArrow);
break;
case Qt::RightToolBarArea:
expandButton->setArrowType(expanded? Qt::RightArrow : Qt::LeftArrow);
break;
case Qt::BottomToolBarArea:
expandButton->setArrowType(expanded? Qt::DownArrow : Qt::UpArrow);
break;
case Qt::TopToolBarArea:
expandButton->setArrowType(expanded? Qt::UpArrow : Qt::DownArrow);
break;
}
if (!expanded)
{
int x, y;
if (vert)
{
//setMinimumWidth(cellWidth);
foreach(QToolBar* toolBar, getToolBarsAtThisSide())
{
if (toolBar->width() > maxWidth)
maxWidth = toolBar->width();
}
//setMaximumWidth(maxWidth);
resize(maxWidth,height());
y = 10;
x = (width()-cellWidth)/2;
}
else
{
//setMinimumHeight(cellHeight);
foreach(QToolBar* toolBar, getToolBarsAtThisSide())
{
if (toolBar->height() > maxHeight)
maxHeight = toolBar->height();
}
//setMaximumHeight(maxHeight);
resize(width(),maxHeight);
x = 10;
y = (height()-cellHeight)/2;
}
foreach(PaletteToolbarButton* button, buttonList)
{
button->move(x,y);
button->show();
if (vert)
{
y += cellHeight;
if (y + cellHeight*2 > height()) break;
}
else
{
x += cellWidth;
if (x + cellWidth*2 > width()) break;
}
}
expandButton->move(x,y);
expandButton->show();
}
else //PaletteBar is expanded
{
int x, y, buttonStrings, maxButtonsInString;
if (vert)
{
maxButtonsInString = height() / cellHeight;
buttonStrings = (buttonList.size() + 1) / maxButtonsInString;
if (buttonList.size() % maxButtonsInString) ++buttonStrings;
//setMinimumWidth(cellWidth * buttonStrings);
//QPoint newpos = pos();
//newpos.setX(newpos.x() - (cellWidth * buttonStrings - 1));
//move(newpos);
QSize s=maximumSize();
QSize s1=minimumSize();
resize(cellWidth * buttonStrings,height());
QSize s2=size();
y = 10;
x = 1;
}
else
{
maxButtonsInString = width() / cellWidth;
buttonStrings = (buttonList.size() + 1) / maxButtonsInString;
if (buttonList.size() % maxButtonsInString) ++buttonStrings;
//setMinimumHeight(cellHeight * buttonStrings);
//QPoint newpos = pos();
//newpos.setY(newpos.y() + (cellHeight * buttonStrings - 1));
//move(newpos);
resize(width(),cellHeight * buttonStrings);
y = 1;
x = 10;
}
foreach(PaletteToolbarButton* button, buttonList)
{
button->move(x,y);
button->show();
if (vert)
{
y += cellHeight;
if (y + cellHeight*2 > height())
{
y = 10;
x += cellWidth;
}
}
else
{
x += cellWidth;
if (x + cellWidth*2 > width())
{
x = 10;
y += cellHeight;
}
}
}
expandButton->move(x,y);
expandButton->show();

if (vert)
{
maxButtonsInString = height() / cellHeight;
buttonStrings = (buttonList.size() + 1) / maxButtonsInString;
if (buttonList.size() % maxButtonsInString) ++buttonStrings;
//setMinimumWidth(cellWidth * buttonStrings);
//QPoint newpos = pos();
//newpos.setX(newpos.x() - (cellWidth * buttonStrings - 1));
//move(newpos);
QSize s=maximumSize();
QSize s1=minimumSize();
resize(cellWidth * buttonStrings,height());
QSize s2=size();
y = 10;
x = 1;
}
else
{
maxButtonsInString = width() / cellWidth;
buttonStrings = (buttonList.size() + 1) / maxButtonsInString;
if (buttonList.size() % maxButtonsInString) ++buttonStrings;
//setMinimumHeight(cellHeight * buttonStrings);
//QPoint newpos = pos();
//newpos.setY(newpos.y() + (cellHeight * buttonStrings - 1));
//move(newpos);
resize(width(),cellHeight * buttonStrings);
y = 1;
x = 10;
}
}
arranging = false;
QSize s3=size();
}//if (buttonList.size()!=0)
}
QList<QToolBar*> PaletteToolbar::getToolBarsAtThisSide()
{
QList<QToolBar*> ret;
QMainWindow* mainWnd = static_cast<QMainWindow*>(parentWidget());
Qt::ToolBarArea area = mainWnd->toolBarArea(this);
foreach(QObject* object, mainWnd->children())
{
if (object!=this)
if (QToolBar* toolBar = dynamic_cast<QToolBar*>(object))
{
if (area == mainWnd->toolBarArea(toolBar))
ret.append(toolBar);
}
}
return ret;
}