I am working in a project where I have a design issue that I don't know how to solve. I would like to find the best solution for extensibility of the code.
The project consists in a web browser with tabs, but in the tabs there are not only webpages, I can have other kinds of widgets.
I am using Qt, and so the widget in the tabs are QWidgets (QWebview and other types that I still have to code myself). Anyway, I'm going to try to keep this question generic enough.
There is a class QWidget from which 2 classes inherit: QWebView and MyWidget.
I have a container (QTabWidget) that can contain both of them, since it can contain QWidgets.
Moreover, I have a button (the previous page button, for instance), that only applies to one kind of QWidget: QWebView.
So, when I press this button, I ask the QTabWidget for the current QWidget and if its a QWebView I do something, otherwise I don't do anything.
That is the problem: I need to be able to distinguish between the two different types: if I ask the QTabWidget to give me the currentWidget, it gives me a QWidget*, but I don't know whether its a QWwbView or a MyWidget and so I have to doa nasty dynamic_cast<> to check the real type.
This means that if I add a new MyWidget2 with another action, I will have to update all my code where there are dynamic_cast<>, and I don't want that.
I have been thinking of command pattern and startegy pattern but I don't think they applu realy well.
Do you have any advise?
Thanks
At an abstract level, it sounds like you need some way of mapping the various widget types to the actions (e.g. "go to previous page") that they can support - that way, when you add a new widget type, you specify its actions as well. Depending on the currently-viewed tab, you can then enable/disable the relevant actions, so that when the user is able to perform an action you know that it will work for the type of tab currently being viewed.
One way of doing this would be to add a virtual member function to your base widget type that returns the relevant actions. You then cast the QWidgets returned by the tab widget to your base widget type. This still involves a cast (because QTabWidget isn't geared up to return widgets of your base widget type), but it gets rid of the maintainability problem when you add new types of widget.
Related
I have a QTabWidget with several tabs, every tab containing a QTableWidget with numbers. Outside of this QTabWidget, I have one button. When the button is pressed, the currently selected widget should be processed. The QTableWidgets are identical in their structure, they just display numbers, and if I have a pointer to one of these widgets, I cannot deduce which tab it came from.
A simple method to identify which widget is currently selected is to call currentIndex(). But this will break when I reorder the tabs in the designer and is probably not working with movable tabs.
Another way is to use currentIndex() and tabText(int index). Like this I have a stable way to find out which tab is currently selected. The disadvantage of this is that I am then dependent on having unique tab texts, and I in general don't like to rely on a UI property to implement functionality.
My solution for now is to give every Widget a different accessible name that I can then read out like this:
QWidget* widget = tabWidget->currentWidget();
QString* name = widget->accessibleName();
This works, but I wonder if there is a better solution, something like the Qt::UserRole that can be assigned to any cell in a QTableWidget.
In Qt widget application, I'd like to have a common base view for all my dialogs, so that I could inherit other classes from it.
This "base/common" view would contain initially a set of buttons at the bottom and a custom frame with data at the top. A place in the middle would be used by derived classes for placing view-specific contents. If the common dialog style changes in the future, changes will be applied in one class only.
Is there any way to use such approach in Qt, since ui files are processed with 'uic' to create classes? Ideally would be to not to lose the ability of using the gui designer, at least for the derived classes.
Any hints much appreciated.
You can make your "base view" as its own ui file with a big QFrame in the middle with nothing in it and name it contentsFrame. Then create your other widgets you want to place inside the empty contentsFrame in designer.
Now you have a couple options. You can have both open side by side in designer, click on your contents widget, select all, and drag everything to your contentsFrame. Then just hit save as and save it as a different widget. If you aren't afraid to leave designer for a tiny bit, you can add your contents widget to the base widget in code. Either way, make sure you are setting the layout for your contentsFrame or everything will look like garbage.
I have a map application and a submenu which has dynamically added objects (i.e. points on a map) added to the submenu, depending on the layer that is loaded. I have the ability to hide each individual objects (i.e. a point) by clicking on the corresponding submenu item. Is there any way to organize the submenu? When there are a lot of points (i.e. 100) the entire submenu takes up the screen. Can I add a scrollbar to a submenu? I looked in the documentation, but couldn't find anything that support this feature.
From this bug report I was able to find out that you could do the following:
submenu->setStyleSheet("QMenu { menu-scrollable: 1; }");
Works like a charm.
There is no such possibility as far as I know.
Maybe you shouldn't use a sub menu for this but prefer a menu entry that show a Point manager GUI of your own which would have a QListWidget displaying all your points items.
I'm aware that this solution will break a (big?) part of your code but I don't see anything else.
I think you may be able to get the effect you want by creating and using your own QStyle subclass (via QApplication::setStyle()), and overriding the styleHint virtual method to return 1 when the StyleHint parameter passed in is SH_Menu_Scrollable. At least, that works for me when I create large QMenu objects and show them as popup menus.... It may also work for QMenus attached to the menu bar, but I havent tried that.
Whilst it is possible by subclassing the QMenu class to create a custom widget and going from there you're better off looking at a better way to display that information. You'll save yourself time and it'll be much easier for your users to not have to scroll through a big list of items in a small area.
I've been wanting to program a simple game with a simple GUI using Qt (Its will be a VERY simple game, nothing fancy). What I've been wondering is, how can I create multiple windows and display them when needed? For an example, a battle screen and an inventory screen. The user should only see one of them, but should be able to access the other one when needed. I was using stacked widget but I'm not sure if that's the proper way. Also, is it better to design the windows in the designer or to code them?
A StackWidget certainly would accomplish what you want to do. The reason why it is not always used for this kind of thing, is that it all the screens are pre-created at the beginning and always exist. This means it takes a little longer to initialize, and you are using more resources than you need at any one time
But as you are saying, if this is a simple game, then I don't see a big problem with it. Just as easily, you could also, create an empty layout and swap the inventory and game panels as needed.
Add my vote to everyone else suggesting to use the designer. It is so much easier to manipulate layouts, actions, and such using the designer then through code.
You can see the Designer manual here
So this is what I would suggest:
Create your "battleScreen.ui" - which is the designer file for your battle screen and everything in it, and then create your "inventory.ui". Both of these could be QWidgets, or QFrames, or whatever makes sense.
Then create your "Game.ui" which will be your QMainWindow.
In your Game main window, you can then add your QStackWidget, and place your inventory, and battle screens in the stack widget.
If you don't know how to do that...
1) drag a QWidget into your form (into the stack widget)
2) select the new QWidget and right-click.
3) Select "Promote to..."
4) Fill out the information to promote the QWidget to your inventory class
Promoted Class Name: The name of your inventory class
Header File: The header file of your inventory class
5) Click add
6) Click Promote.
Hope that helps.
Since I'm not sure what your goals are I can't advise whether or not the stacked widget is appropriate but I think you can accomplish quite a lot using the designer and style sheets. If you need to code some parts of the GUI, you can always drop in a place holder widget and either replace it with coded items or make them children of the place holders.
A general answer for a general question:
Use the Designer to create your windows; hide and show the auxiliary windows as needed.
Use a flow manager class to manage the visibility of a related set of windows.
The stacked widget is useful for managing a button/icon whose appearance changes based on state; the different representations live in the stack.
I'm making a game GUI API. It is coming along very nicely except for one aspect. I want themes similar to how GTK works. The way I want it to work is that every GUI element will have a default Windows9X-like way of drawing themselves. If it is found that a theme is set for that type of widget, it will be drawn with those bitmaps.
My original concept was to create a Theme class which would have getters and setters for the bitmaps.
for example:
themeManager.setButtonHover(Bitmap *bitmap);
The problem with this, is that it is not flexable if I want to create new types of Widgets. I may eventually want to create a superButton which would use a different theme than a button. This is the flaw with that concept. The concept I'm thinking of going with is that each widget type has static methods to set the theme for itself and the constructor uses that.
Are there better ways of doing this that I'm not thinking of? Since it is an API, I want to avoid reading text files, so reading the theme from a text document is not an option.
Thanks
May be template the superButton on a policy and then have a default policy which does the default and the user has the option of providing a different policy? The policy could then define the attributes of the button (such as the hover image etc.) - does what I describe make sense?