I'm making a Qt widget (let us call it A) that really is a subclassed QGraphicsView. However, I don't want to expose QGraphicsView methods in my widget, just the basic QWidget interface and some of my own methods. Thus, I'd like to encapsulate an instance of A as a member of a simple QWidget subclass we'll call B.
Now I wonder, what is the proper way to draw this? So far I've given B a layout whose only item is the A member. But this feels sort of wrong; for example, I'll need to override default layout settings to avoid adding extra margins etc. This leads me to feel that there is some correct way to do this that I'm missing. Any thoughts?
Edit: In the setting of RedX' answer, my question becomes: What is the proper way to use gv in this setting? Give A a layout and add gv to it, or override A's painting methods to instead use those of gv? Or something else?
I don't think there is a better way. If you don't want to use a layout, you can override the parent's resizeEvent() like this:
void A::resizeEvent( QResizeEvent* ) {
m_graphicsView->setGeometry( QRect( 0, 0, size() ) );
}
I think you are trying to do this?
class A : public QWidget{
QGraphicsView* gv; //use this to do whatever you need
};
This should expose a as a QWidget and internally you'd use the gv to do whatever you need from the QGraphicsWidget.
Related
Iam looking for a good and easy way to propagate a variable, in my case a string from QWizard on to the pages. I have tried to use fields but without registering it this won't work.
So on the third page of my wizard I need a path to a folder where some data can be found, this is used to init a QFileDialog. This QString is not directly coupled to a QWidget. So I can not call registerField on it.
pseudo code:
// setup wizard:
QMyWizard wiz;
QString s = "c:\\";
wiz.SetFolder(s);
I can of course in the Wizard SetFolder function access the page by looking it up and casting but I find this quite ugly. So Is there a good solution to pass on global variable without registering to widgets?
Thanks!
I'll answer my own question.. I did not find handy functionality in the wizard code itself. Now I am using the ability of any derived class from QObject to hold properties in a map from string to QVariant. In the wizard pages you can acces the properties of the parent now.
http://qt-project.org/doc/qt-4.8/qobject.html#setProperty
I am trying to teach myself design patterns. I was reading about the Decorator pattern, and there's one thing that I can't quite get. Here is an example found on wikipedia:
Let's say I want to implement a window that can scroll both horizontally and vertically, I would do this:
Window win=new Window();
win=new HorizontalScrollBarDecorator(win);
win=new VerticalScrollBarDecorator(win);
Since win is a reference of type Window, I can call neither drawHorizontalScrollBar() nor drawVerticalScrollBar() (apart from the code in the concrete decorator itself), and of course it would not make sense to change the reference type.
So, how can I "add new behaviour" (I.E. implement new methods) with decoration?
Nevermind, I think I got it:
Through decoration you can't "add new behaviour" as I had interpreted it (drawHorizontalScrollBar() is not visible from outside the HorizontalScrollBarDecorator class, which means it's probably called by its draw() method), BUT you can extend methods of the base class.
It's like extending the base class, overriding the draw() method and then calling super.draw();, with the difference that you can apply multiple decorators, but you can't inherit from multiple classes.
I thought I was beginning to understand this but it seems not.
I am trying to connect together a stacked widget so that the children can send a message to the parent to tell it to change the view. The QStackedWidget is a child of the main window and its pages are promoted fomrs that I created myself. I think that's the right way to do it?
So within one of the children forms I tried the following:
// Set up a mapping between the buttons and the pages
QSignalMapper *mapper = new QSignalMapper(this);
mapper->setMapping(ui->automatedButton, 1); // Value of the index
connect(ui->automatedButton, SIGNAL(clicked()), mapper, SLOT(map()));
connect(mapper, SIGNAL(mapped(int)), ((QStackedWidget*)parentWidget()), SLOT(setCurrentIndex(int)));
But that doesn't seem to work. I click the button and nothing changes. However if i do this:
void MySelectionForm::on_automatedButton_clicked()
{
((QStackedWidget*)parentWidget())->setCurrentIndex(1);
}
Which I thought was the same as what I was doing before?
I do see on message when running which I guess is associated:
QObject::connect: Cannot connect QSignalMapper::mapped(int) to (null)::setCurrentIndex(int)
Have you checked that parentItem() is not returning NULL when you call QObject::connect()? It sounds like maybe the parent item is being set after the constructor, which would mean that parentItem() would indeed return NULL. I suspect that might be how Qt Designer rolls. If so, you would need to connect the signal/slot outside of the constructor, either in another method (one that is not called inside the constructor), or outside of the child altogether.
According to the message,
((QStackedWidget*)parentWidget()), SLOT(setCurrentIndex(int)));
leads to
(null)::setCurrentIndex(int)
which means parentWidget() is NULL.
This basically means that the forms are not a child of the QStackedWidget.
If you create your forms manually, you have to do something like this
MyForm *form = new MyForm( ui->stackedWidget );
Just out of curiosity, I am making an effort to optimize every part of our flex app (which is a small part of our app in general). Currently, I am working on optimizing all of the buttons/skins. I have linked a few of the buttons that I use, and some sample code I am using to generate them.
Please advise on how to make this more efficient, usable, and just better overall. Thanks!
As you can see, our buttons can be pretty different, but have a similar look and feel. Currently, I am creating 'stateful skins,' by setting up something like this:
skin: ClassReference('com.mysite.assets.skins.NavigationButtonSkin');
Then, NavigationButtonSkin looks something like this:
public class NavigationButtonSkin extends UIComponent {
// imports, constructor, etc
protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
// initialize fillColors, fillAlphas, roundedCorners, etc
switch( name ){
case 'upSkin':
fillColors = [getStyle('backgroundColor'),getStyle('backgroundColor2')];
break;
// do the same for overSkin, downSkin, disabledSkin, etc
}
// use this.graphics to draw background
// use this.graphics to draw border on top of background
}
}
I commented out some of the straight forward parts, but let me know if this is a bad/inefficient way of doing this - and how to improve.
Thanks!
In terms of performances, it would be better that your skin inherits from ProgrammaticSkin instead of UIComponent.
ProgrammticSkin itself inherits from Shape and provides utility methods for skinning such as verticalGradientMatrix, drawRoundRect, ...
That's all I can say looking at your code.
Good point is you use programmatic skin instead of bitmap/swf based skins.
Okay, I'm not getting where you're getting at with this. You just want to know if you're doing it right? I'm assuming that your skin: ClassReference('com.mysite.assets.skins.NavigationButtonSkin'); is added to the css of a Button, which is good, however I don't see why you're doing it all in Actionscript. Seems inefficient and essentially you're losing all the ability of mxml layouts and support for Catalyst (if you'd ever need it in the future).
Try creating a skin in Flash Builder, it'll create an MXML with the default button skin where you can just edit it as you please. It's also A LOT easier to do state based design using mxml over actionscript. You should modify from there on and have a separate skin for each button types.
EDIT: oh crap, didn't see this was Flex 3... Get with the program ;) Just listen to what Florian said.
I have a K* window, and within it, a widget which needs the events filtered.
For example I do not want the possibility of clicking it...
How can I do that?
Have I to use eventfilters? In this case, what's the best way?
but my problem is that I can't subclass my widget,because it's a TerminalInterface->widget(), not an object like others :\
Besides the setEnabled sledgehammer approach in the first answer, there are two other approaches, one of which is to use eventfilters.
The other is to subclass the widget, and then reimplement, say, the mouse* events. Simply leaving them empty will prevent any mouse interaction. So:
MyWidget : public QSomeWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent);
protected:
void mousePressEvent(QMouseEvent *) {}
.. etc ..
};
QWidget has an enabled property. Just call widget->setEnabled(false) and this will prevent it from accepting mouse clicks. It may also modify its appearance: for example a QPushButton will be grayed out.
Event Filters sound like overkill for what you want.
It looks like eventFilter() is what you want.
Here's the section of Qt docs that talk about it:
Event Filters
Basically you have to create a class that inherits QObject and then implement the virtual function eventFilter(). Then call the installEventFilter() method on the object that you want to filter with the filter as a parameter.