The QDialogButtonBox widget automatically reorders it's buttons to meet the expectations of users on different platforms. I'd like to follow this behavior, but with my own button labels (e.g. 'Import' instead of 'OK'). How can I achieve this? Is it possible to use QMessageBox, or do I need to write my own implementation? I'm writing my application with PyQt4, and Qt Designer.
See screenshot below of QDialogButtonBox on OS X in Aqua and Cleanlooks styles.
QDialogButtonBox can do this for you, but you will need to create a dialog to put one in first (a trivial amount of work).
...
auto buttons = new QDialogButtonBox( this );
buttons->addButton( "Import", QDialogButtonBox::AcceptRole );
buttons->addButton( "Cancel", QDialogButtonBox::RejectRole );
...
The docs are here (it's C++, but I'm sure can follow it), the general idea is that ButtonRole is used by the current style layout to rearrange the buttons.
Related
I want to use btn1 to send a signal to the slot function of deviceTypeSelect, but btn1 can only be associated with QStackedWidget.
There are two problems.
The first is conceptual: Designer cannot know anything about custom slots that are going to be implemented in a promoted widget, and it even should not. The connection to those slots can only be achieved programmatically, and that's for good reasons: Designer cannot "inspect" (nor it should) the source of the files that will be promoted, and it's also completely possible that one would promote a widget and use different classes with the same design files.
The other problem is technical: the "pages" of multipage widgets like QStackedWidget or QTabWidget cannot be used as signal targets on Designer. I don't know if it's just a missing feature or it's by design (knowing how multipage widget plugins are dealt with I wouldn't bet about the it), but unfortunately it really is not possible.
If you want to connect to standard QWidget slots (setEnabled() etc.), set a dummy boxed layout on the page, and add another QWidget in it, but if you use custom slots, as explained before, those must be manually connected from your code.
I'm very keen on being able to use the keyboard to do everything with a GUI and am currently exploring QTreeView and QTableView among other things.
I'm adding a lot of my own hotkeys (shortcuts) and am devising a method to automate a user list or guide to these available hotkeys.
But something like QTreeView also comes with its own built-in hotkeys, e.g. arrow keys for navigation, F2 to start editing, Ctrl-A for "select all", etc.. I want to get a comprehensive list of these and include them in the automatically generated user guide.
I've got to this page, for example, but I haven't really got a clue how to dig down into PyQt5 components to unearth this kind of information programmatically.
There's some interesting functionality, probably unknown to many users, with QTreeView: e.g. if, in column 0, you have a tree structure you can skip from label (text) to label by pressing the first letter of each one's label. But if you enter 2 (or more) keys quickly enough this also works: entering "ra" will skip over "Roma" and "Rimini" to "Ravenna" even if "Roma" and "Rimini" come first. It turns out that this is implemented by QTreeView.keyboardSearch ... but what I want to know is whether it's possible to find details of the "mapping" functionality for this and other keyboard enablements, often implemented by keyPressEvent, programmatically. Having looked a little at the PyQt5 files it seems that a lot of PyQt5 functionality may ultimately be contained in .dll files (this is a W10 machine), so I'm not particularly optimistic.
Each widget has a certain behavior depending on the hotkeys pressed, so there is no documentation that indicates all the cases, so you will have to review the documentation of each class and the parent class. So for example to understand the behavior of QTableView you should also review the documentation of QAbstractItemView, QAbstractScrollArea and QFrame (the same is for QTreeView), considering the above we can collect information:
void QAbstractScrollArea::keyPressEvent(QKeyEvent *e)
This function is called with key event e when key presses occur. It
handles PageUp, PageDown, Up, Down, Left, and Right, and ignores all
other key presses.
QAbstractItemView:
void QAbstractItemView::keyPressEvent(QKeyEvent *event).
This function is called with the given event when a key event is sent
to the widget. The default implementation handles basic cursor
movement, e.g. Up, Down, Left, Right, Home, PageUp, and PageDown; the
activated() signal is emitted if the current index is valid and the
activation key is pressed (e.g. Enter or Return, depending on the
platform). This function is where editing is initiated by key press,
e.g. if F2 is pressed.
(emphasis mine)
QTableView and QTreeView when inheriting from QAbstractItemView have the same hotkeys.
I am trying to build a GUI which will:
Load a file with parameters which describe certain type of problem.
Based on the parameters of the file, show only certain tab in QTabwidget (of many predefined in Qt Designer .ui)
I plan to make a QTabwidget with, say 10 tabs, but only one should be visible based on the parameters loaded. Enabling certain tab is not an option since it takes to many space and the disabled tabs are grey. I do not want to see disabled tabs.
Removing tab could be an option but the index is not related to a specific tab so I have to take care of the shift in the indices. And furthermore if user loads another file with different parameters, a good tab should be added and the current one removed.
My questions are:
How to do this effectively?
Is it better to use any other type of widget?
In Qt designer, is it possible to define many widgets one over another and then just push the good one in front. If yes, how? And how to edit and change any of them?
If using RemoveTab, how to use pointers on tabs, rather than indices?
I use PyQt4
Use a QStackedWidget, which is exactly the same as a tab-widget, but without the tab-bar (which you don't need).
This widget is available in Qt Designer. The context menu has several commands for adding/removing pages and so forth. Note that the arrow buttons in the top-right corner are just there for convenience: they won't appear in your application.
Pages can be added/removed at runtime with addWidget/removeWidget:
index = self.stack.addWidget(self.page1)
self.stack.removeWidget(self.page1)
You can access the pages using either indexes or widget references.
I see that this thread is kinda old. But I hope this will still help.
You can use the remove() method to "hide" the tab. There's no way to really hide them in pyqt4. when you remove it, it's gone from the ui. But in the back end, the tab object with all your settings still exist. I'm sure you can find a way to improvise it back. Give it a try!
Maybe I'm jumping into the deep end, but I'll give it a shot.
Here are some useful features of Tkinter:
The Tkinter Canvas widget is an object oriented drawing canvas. The elements of the drawing are essentially widgets themselves, as they can be moved, modified, and bound to events.
Tkinter uses bindings to trigger callbacks. The event is passed as a string. Custom events can be easily created with event_generate.
Tkinter has the after method, which waits for a specified amount of time without freezing the GUI.
Tkinter has predefined fonts like TkDefaultFont, and colors like systemButtonFace, which are dependant on the system.
My questions are:
What are the pyQt equivalents of these features (especially the bold ones)?
How can I "bind" elements of a widget (e.g. the label of a checkbutton only) to an event?
In Qt and PyQt events are called signals and you bind to them using slots (docs here). Generally speaking what you do define a slot with an # decorator.
class WindowImpl (QtGui.QMainWindow, Ui_TremorMain, Ui_Graphs):
def __init__ (self, buffer, parent = None, configuration = None):
# do some initialisation here (not GUI setup however)
#QtCore.pyqtSlot(int, name="on_confSelectorCombo_currentIndexChanged")
def confChanged (self, newConf):
# do some stuff here to handle the event
The above would be triggered on the currentIndexChanged event of an object called confSelectorCombo. The setup of the confSelectorCombo is done in the GUI builder or Qt Creator as Nokia has decided to call it. This really is what you want to use to get started. There's tutorials here on using Qt Creator. Obviously you'll want to go through the docs and see what signals are emitted by which widgets.
As for the font stuff all I know is what it says on the docs:
If you have not set a font for your application then the default font on your
machine will be used, and the default font can be different on different
machines. On Windows the default Windows font is used, on X11 the one in qtrc
can be used. If a default font can’t be found, then a font specified by Qt
will be used.
The QStyleSheet and QStyle act as proxies for changing the appearance of widgets (QStylesheet,QStyle).
As for making the application wait I found this
QTime dieTime = QTime::currentTime().addSecs(2);
while( QTime::currentTime() < dieTime ):
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
There is also QThread.sleep() (docs), depending on what kind of an effect you want. Probably also worth looking at the threading support over at Qt docs
Overall in finding information about how to do stuff in PyQt I have found it surprisingly useful to look at the Qt documentation and then just writing the stuff in Python. 9 times out of 10 this works. On another note, it's probably also worth looking into PySide which is another python Qt library. I've haven't used myself before as it has been in the works previously but I noticed that they had released a 1.0.6 version.
UPDATE
Just to reiterate Luke Woodward below, you can use QGraphicsScene and QGraphicsView to render stuff in an object oriented way. The QGraphicsScene doesn't actually render anything it just a scene graph, the QGraphicsView is then used to render the contents of the scene graph. For low level drawing there´s also QPainter - there's a basic drawing tutorial here. It's also worth looking at QGraphicsItem which is the base for all graphics items and
includes defining the item's geometry, collision detection, its painting
implementation and item interaction through its event handlers
docs here. The Context2D provides an HTML canvas (if I'm not mistaken through the use of WebKit). The canvas itself only has a changed slot, but any objects you place on the canvas will/can have more slots. There's a fairly complete looking tutorial on Context2D and Context2DCanvas here. For an explanation as to why so many different ways of rendering stuff, you'll have to ask someone else. My two cents is that is has something to do with the fact that Qt is supposed to work everywhere and Trolltech and later Nokia wanted to provide lots of choice. Luckily the docs are really good.
I would like to have my pyqt aplication have tabs in the menu bar like Google Chrome :)
Any suggestions or a simple example on how to do it?
I did find these relevant link:
- http://ivan.fomentgroup.org/blog/2009/03/29/instant-chrome/
You have to use the Qt.FramelessWindowHint for that, and then create your own Max, Min, Close buttons as Widgets and add them there. I have a good working toolkit for these types of softwares: http://traipse.assembla.com/spaces/ghostqt
In your case you should reclass the resizeEvent so you can change the flags. If the window is maximized you will not need to worry about moving it around, but if it is not maximized you can remove the Qt.FramelessWindowHint flag and get your title bar back; just like Chrome does.
Is that what you are looking for?
If I understand correctly, just create a QWindow that contains a QTabBar widget(and not a QMenuBar, or simply use a QTabWidget as your main program widget.
you need to do the following:
remove window border (FramelessWindowHint)
Implement your own window moving and resizing code
Insert tabbar on the top, and add buttons for close etc. to it (or create a frame that will contain the tabbar and buttons)
And that's all that was done in Webbie (the link you provided) :)