PDA

View Full Version : Custom widget with frame like QLineEdit



cil
14th April 2010, 13:24
Hi All.

I would like to build a custom widget that appears with the same frame and background of QLineEdit, whatever they are. The inner content of the widget will be drawn by my paintEvent method.

Till now I was able to draw the same frame, inheriting my widget from QFrame (instead of QWidget) and setting the frame style to StyledPanel | Sunken. This isn't enough, because I have no background (QLineEdit has a background, usually white).

There's a way to tell Qt "draw this widget like QLineEdit"?

I'm doing this through PyQt4 (if matters...).

Thank you.

wysota
14th April 2010, 13:49
If it is just about background then you need to tell the frame it should draw one (QWidget::autoFillBackground) and what colour it should use for it (QWidget::setBackgroundRole(QPalette::Base)).

cil
14th April 2010, 14:06
I tried this (python code):

palette = self.palette()
palette.setColor(QPalette.Window, Qt.white)
self.setPalette(palette)
self.setAutoFillBackground(True)
and this, like you suggested:

self.setBackgroundRole(QPalette.Base)
self.setAutoFillBackground(True)
both draw a white filled rectangle under the widget's frame, but this rectangle is slightly bigger than the frame and this is awful (at least with my KDE4/Oxygen widget style, which has rounded corners for all widgets; the white background of QLineEdit is, obviously, well contained inside the frame).

thank you for your help.

borisbn
14th April 2010, 14:45
see QStyle::drawPrimitive ( QStyle::PE_PanelLineEdit, ... ) (http://qt.nokia.com/doc/4.6/qstyle.html#drawPrimitive)

faldzip
14th April 2010, 19:54
There's a way to tell Qt "draw this widget like QLineEdit"?

Yes, you can derive your class from QLineEdit.
On the other hand you can draw whole controls with QStyle or QStylePainter. Read about those classes in Assistant.

cil
15th April 2010, 08:18
Deriving from QLineEdit seems to me a little forced, because I don't want to modify/extend the QLineEdit behaviour but I want only its appearance. Anyway, If there are no technical reasons to don't derive from QLineEdit for a totally different scope, this could be the simpliest solution.

QStyle seems promising! But not so easy to understand... I'll look for some examples. Thank you.

aamer4yu
15th April 2010, 10:03
What if you set the stylesheet with a thick border ?
something like myLineEdit->setStyleSheet("border : 2px solid black;");

Check the stylesheet example in Qt demos...

wysota
15th April 2010, 10:06
Go for QStyle as faldżip suggested, it's easy, really.

cil
15th April 2010, 10:29
I think this is the right direction... and now I understand the borisbn suggestion.

in my paintEvent method (python code):

def paintEvent(self, event):

painter = QPainter(self)

option = QStyleOption()
option.initFrom(self)
self.style().drawPrimitive(QStyle.PE_PanelLineEdit , option, painter)
... other drawing operations...

but this has no effect. I get only my drawing operations.
I have some troubles to understand what to do with the QStyleOption object. Maybe the problem is this.

wysota
15th April 2010, 10:39
I think you should be using QStyleOptionFrame(V3). It's best to look into QLineEdit source code and verify that instead of guessing.

cil
15th April 2010, 11:18
I read qlineedit.cpp, as you wisely suggest. Doing this gave me the inspiration
for this solution (python code):


class MyWidget(QWidget):

def __init__(self, parent=None):

super(MyWidget, self).__init__(parent)

self.styleoption = QStyleOptionFrameV2()
qle = QLineEdit()
qle.initStyleOption(self.styleoption)


def paintEvent(self, event):

painter = QPainter(self)
self.styleoption.rect = self.contentsRect()
self.style().drawPrimitive(QStyle.PE_PanelLineEdit , self.styleoption, painter)


In other words, I use a QLineEdit to fill in the QStyleOption object for me.
Then I can use drawPrimitive (borisbn's hint) to have my widget drawn as
I like.

Thank you for you patience, I learned some useful things.

wysota
15th April 2010, 11:43
Hmm... Not very efficient to create a line edit just to fill in a few properties.

cil
15th April 2010, 11:56
It's true, but there aren't any visibile performance problems and my code is really simple and compact. I can always explode initStyleOption() whenever it becomes necessary.

wysota
15th April 2010, 11:58
Yeah, but it's still ugly :)