How do you switch between two windows in PyQt? - python

I want to make a new PyQt window show up and hide the current window when I click a button. After playing around for hours, I haven't found a good way to do this.
When I try to show a new QDialog and hide the current one, the program closes. It works if another window is open. I believe this is because it is viewing the last window as closing and terminates, or maybe the new QDialog is falling off the stack.
My current method involves storing the QDialog as a variable in the current dialog, then showing it and hiding current dialog. This seems like a total hack, though.
Example below:
def _createQuestion(self):
# initialization of the UI and everything goes on in the constructor
self.dialog = QuestionBanks()
self.dialog.show()
self.hide()
Is there a better way of switching a single window to a distinct different single window in PyQt4?

Related

How to set focus to the old window on button click in PyQt5 Python?

My Current Project is to create a On Screen Keyboard for my personal usage with my personal functionality. I made gui and primary function in PyQt5 with Python. I managed to type the letter on button click with pyautogui.write() method. But the problem is, where I want to type there is no focus. suppose I want to write on chrome's address bar or any other input field on my monitor. when I click on button to type a letter, chrome lost focus. I want to set focus to the old window while press on any button. I searched on google about this but didn't found any answer. How can i set focus to old window? or is there any better way to type on focus lost state?
You should not try to "set the focus back", as it would be almost impossible to know what window had the focus before (and a new window might raise in the meantime). What you should actually do is to prevent your window to get focus at all, thus avoiding it to steal focus from the others.
In order to achieve this, you must set the appropriate window flag (or initialize the widget with it using the flags keyword argument), which for this is Qt.WindowDoesNotAcceptFocus.
Note that you might also want to set the Qt.WindowStaysOnTopHint in order to always keep your window above the others:
class MyKeyboard(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowFlags(
QtCore.Qt.WindowDoesNotAcceptFocus
| QtCore.Qt.WindowStaysOnTopHint
)

Python/PySide: How to make a widget that will stay on top of the main window, but not cover up other widgets?

So I have a script running inside another program (The Foundry's Hiero) and I'm just making a new QWidget object, and calling self.show()
Now, I can set it to self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint), so my window will stay on top of the main window, even if you click on something in the main window.
The problem is, this is a sort of popup window that you configure settings in, and it triggers other QWidget popups. If I set my window to WindowStaysOnTopHint, those subdialogs that my widget triggers end up beneath my widget.
Is there a way in PySide/PyQt to make a window stay on top/keep focus from the main application window in particular, but not everything?
You can use the QApplication.focusChanged signal to raise your widget up when Hiero's main window is selected. Then you would just need to remove the WindowStaysOnTopHint flag.
I'm not familiar with Hiero's API, but I'm guessing you could try something like:
def raiseMyWidget(old, new):
if new == hiero.ui.mainWindow():
myWidget.raise_()
QtWidgets.QApplication.instance().focusChanged.connect(raiseMyWidget)
Hope this helps! You can take advantage of the old parameter or some other means to make sure that your widget isn't raised above the others as well.

Is it possible to see if the file is being dragged over the window in Kivy, Python?

What I want to achieve:
I want to detect the situation when the user is dragging a file over the Kivy app window.
What I already know:
I know how to detect hovering mouse coursor over widgets (with on_mouse_pos), I also know how to detect if a file is dropped onto the window (with on_file_drop).
So, is it possible to see whether the cursor is hovering over the window and "holding" a file? Because then I want to display some prompt (eg. 'Drop HERE'). I hope you get the idea :)
I'm not really sure, because there's this thing with SDL2 (and probably even with old pygame) when the Window just pauses (try some animation or something) when you e.g. drag it with the window decoration (the thing where title and _ O X are). That is the behavior if you do something with the Window directly.
Although, the Window looks like it behaves normally (doesn't pause itself), when you drag file on top of it (I tried with examples/animation/animate.py), to do such thing you'd need to do either the hovering behavior + handling the collisions or bind to mouse_pos.
However, when binding to mouse_pos, it seems like the Window still isn't capable of handling the input from outside and at the same time get mouse properties correctly (I think it's similar to the behavior when you click & drag outside of the Window and Button remains pressed, but this is kind of inversed).
edited animate.py:
class TestApp(App):
def on_mouse_pos(self, win, args):
print args
...
def build(self):
...
from kivy.core.window import Window
Window.bind(mouse_pos=self.on_mouse_pos)
return button
Therefore if you can't get even mouse position when a mouse button is being held, I don't think such an action is possible. You can however make the areas where you want to drop the file already different (e.g. change background) when you'll expect a user to drop the file - a very dirty workaround from UI side for such a problem.
Side note: Kivy should be able to get most (if not all) SDL2 window events via Cython, therefore if you find such event in SDL2 that would make fetching mouse position possible, such action could be performed, feel free to make a feature request in kivy/kivy or make a pull request.

pyqt: Don't lose focus on mainwindow

I have a ctrl+f dialog and when I press the window, it causes the main window to lose focus. Is there a way to have both windows have focus?
Kind of, but not really. Only one window can claim focus on the desktop/operating system level. You want this to be your application or main PyQT object. Then, what you want to do is define a new window type (QObject) that will be treated like a toolbox/dialog within the parent application. This will set a child-like focus attribute. Your application will retain focus on the desktop level, and now you have another inner-focus attribute for windows spawned from within your app.
QtGui QStyleOptionToolBox
StackOverflow: pyqt popup window

How to implement a signal/slot defined in Qt Designer

I am trying to connect the click() signal of a button to my own function. The button is in a widget that I created with QT Designer. I load the .ui file with QUiLoader like so:
class MyWidget(QtGui.QMainWindow):
def __init__(self, *args):
QtGui.QMainWindow.__init__(self, *args)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile("pyside_ui_qtdesigner_form_test.ui")
file.open(QtCore.QFile.ReadOnly)
self.myWidget = loader.load(file, self)
file.close()
self.setCentralWidget(self.myWidget)
btn = self.myWidget.findChild(QtGui.QPushButton, "HelloWorldButton")
btn.clicked.connect(self.slot1)
def slot1(self):
print "Received"
Is this the correct way to connect to button clicked() signal? I see that I can wire up signals and slots directly in Qt Designer, but how do I prepare and get to such wire-ups in the code?
Side question: The code above works, but the main window shows in the wrong size. How do I ensure that it appears in the right size? Should I do this with minimum height/width constraints?
Use Signals and Slots Editing Mode for connecting predefined Qt signals directly to predefined Qt slots.
So for "Close" button on a simple dialog, you can just drag a connection from the button to the dialog, select the clicked() signal and the reject() slot, click "OK", and there would be nothing more to do.
For signals and/or slots you want to define yourself, you do not need to "prepare" anything in Designer beforehand. Everything should be done in your own code.
Your example already demonstrates this fairly well, but the connection could be done much more simply and cleanly, like this:
self.myWidget.HelloWorldButton.clicked.connect(self.slot1)
As for your main window having the "wrong size": it's difficult to tell from the code you've shown, but it may be because you did not set a layout in the widget that you are loading.
BTW: is there a specific reason you're using QUiLoader? Compiling python modules using pyuic4 is much more flexible, and you can learn a lot from the code that is generated.
EDIT
For me, setting a layout on the main form cures the resizing problem you are talking about.
If you don't know how to do that: in Designer, right-click on a blank part of the main form, and then select Layout/Layout in a Grid from the menu (there's also a button on the toolbar for this).
Once you've done that, resizing the form will automatically stretch it to fit the contained widgets.
I edited the .ui file:
Close QT designer
Edit the .ui in the slot/signal area
Run it

Categories