PDA

View Full Version : Imitating a ComboBox



metalinspired
14th August 2009, 22:35
Hi all. My first post here :)
I'm trying to "imitate" a combo box. Original combo doesn't cut it and I can't achieve what I need by sublassing it so I decided to make one. I used a QLineEdit and putted a QToolButton in it. It works fine but there’s one thing bothering me. Button height is 4 pixels smaller than that of line edit. Thus if a user puts his mouse over a frame of line edit, that can be seen below and above button, the mouse pointer will change to text cursor. I figure I could simply put some sort of rect behind button that will have the same height like line edit, be transparent and will do nothing except stop mouse pointer from changing. I tried, and tried but nothing that came across my mind worked. Maybe because I'm a beginner in QT :)

Boron
15th August 2009, 13:37
You did not mention why you don't use QComboBox. You write "Original combo doesn't cut it". Cut what? Cut the text if it is too long?
Maybe QComboBox can do what you want, but you just didn't find it.

metalinspired
15th August 2009, 14:45
You did not mention why you don't use QComboBox. You write "Original combo doesn't cut it". Cut what? Cut the text if it is too long?
Maybe QComboBox can do what you want, but you just didn't find it.

By "doesn't cut it" I meant I didn't find a way to achieve what I had in mind mostly because I’m a beginner :D I need a user to be able to enter text while list of possible choices is displayed as a drop-down list. With a combo when you show the drop down list you can’t enter anything until list is closed. I tried using QCompleter. But couldn’t get it to show the current completion as selected. It just puts a doted frame around current completion.

axeljaeger
16th August 2009, 10:05
You can have a look in the QtCreator sourcecode for the special lineedit bottom left of the mainwindow. It does autocomplete while you are typing.

Also see http://qt.nokia.com/doc/qq/qq07-customizing-for-completion.html but be warned, it is Qt 3.

metalinspired
16th August 2009, 13:17
You can have a look in the QtCreator sourcecode for the special lineedit bottom left of the mainwindow. It does autocomplete while you are typing.

Also see http://qt.nokia.com/doc/qq/qq07-customizing-for-completion.html but be warned, it is Qt 3.


Thank you. Code in that document has similar functionality that I’m trying to achieve, and is pretty close to what I had in mind on how to solve this. The button is there to let user choose without having to type anything. Any idea on how to solve my mouse pointer problem?

axeljaeger
16th August 2009, 13:32
Do you put the button INSIDE the text field? Why not put it next to the lineedit using a layout?

metalinspired
16th August 2009, 14:08
Do you put the button INSIDE the text field? Why not put it next to the lineedit using a layout?

Yes, it is inside lineEdit. It looks more like true combo that way. Here's how I did it so far.

.cpp

#include "mycombobox.h"
#include <QToolButton>
#include <QResizeEvent>
#include <QSize>

MyComboBox::MyComboBox(QWidget *parent) : QLineEdit(parent)
{
// Button ---------------------------------------------------------------- //
button = new QToolButton(this);
this->setButtonPosition(this->buttonPositionRight);
button->setCursor(Qt::ArrowCursor);
button->setCheckable(true);
button->setStyleSheet("QToolButton { border: 1px solid #b2c4e5;"
"border-radius: 1px;"
"image: url(../images/downarrow.png);"
"background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,"
"stop: 0 #e1eafe, stop: 1.0 #bccefa);}"
"QToolButton:checked { border: 1px solid #b0c5f2;"
"background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,"
"stop: 0 #6e8ef1, stop: 1 #d2deeb);}"
"QToolButton:checked:icon { top: 10px; left: 10px; }"
"QToolButton:!checked:hover { background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,"
"stop: 0 #fdffff, stop: 1 #b9dafb);}");
button->show();
// ----------------------------------------------------------------------- //
}

void MyComboBox::resizeEvent(QResizeEvent *event)
{
setButtonGeometry(event->size());
}

void MyComboBox::setButtonPosition(buttonPosition pos)
{
if(pos == this->buttonPositionLeft)
buttonPos = this->buttonPositionLeft;
else
buttonPos = this->buttonPositionRight;

setButtonGeometry(this->size());
}

void MyComboBox::setButtonGeometry(const QSize &lineEditSize)
{
int buttonWidth = 14;
int buttonHeight = lineEditSize.height() - 4;
int buttonX = 2;
int buttonY = 2;

if(buttonPos == this->buttonPositionLeft)
this->setTextMargins(buttonWidth, 0, 0, 0);
else
{
// Sets the button to be on the right side and sets margins of the QLineEdit
buttonX = lineEditSize.width() - (buttonWidth + buttonY);
this->setTextMargins(0, 0, buttonWidth, 0);
}

button->setGeometry(buttonX, buttonY, buttonWidth, buttonHeight);
}


.h

#ifndef MYCOMBOBOX_H
#define MYCOMBOBOX_H

#include <QLineEdit>

class QToolButton;
class QLineEdit;
class QSize;

class MyComboBox : public QLineEdit
{
Q_OBJECT
Q_ENUMS(buttonPosition)

public:
MyComboBox(QWidget *parent = 0);
void resizeEvent(QResizeEvent *event); // ...for button position...
enum buttonPosition {buttonPositionLeft = true, buttonPositionRight = false};
void setButtonPosition(buttonPosition);


protected:
// Button --------------------------------------------------------------------------------- //
QToolButton *button; // Button to show drop-down list
buttonPosition buttonPos; // Button position (true -> Left, false -> Right)
void setButtonGeometry(const QSize &); // Sets button position and size
// ---------------------------------------------------------------------------------------- //
};

#endif // MYCOMBOBOX_H

axeljaeger
16th August 2009, 14:14
No no, don't do that.

Only because "it looks more like a real combobox" on some operating system, the approach is doomed to fail on other operating systems/skins.

You will also be able to have text UNDER your button. Thats not good also. Make both lineedit and button next to each other, disable the frame of the lineedit and maybe make a frame around all. That is basically how the real combo is implemented.

See also http://labs.trolltech.com/blogs/2007/06/06/lineedit-with-a-clear-button/

metalinspired
16th August 2009, 14:43
No no, don't do that.

Only because "it looks more like a real combobox" on some operating system, the approach is doomed to fail on other operating systems/skins.

You will also be able to have text UNDER your button. Thats not good also. Make both lineedit and button next to each other, disable the frame of the lineedit and maybe make a frame around all. That is basically how the real combo is implemented.

See also http://labs.trolltech.com/blogs/2007/06/06/lineedit-with-a-clear-button/

For text under the button I used setTextMargins to avoid it. Also I doubt that my application will ever be used on other operating system than widows, but even difference between the way XP and Vista look could pose a problem, so your argument is completely in place. I will try the approach you mentioned and if I get stuck I’ll be back with more questions :)