I'm writing a PyQt5 app that includes some text widgets. If I copy some text to the clipboard, I can paste it into other programs only while my program is running. If I close my program, its clipboard data disappears.
I see there is an open Qt bug about this which suggests calling the Windows API OleFlushClipboard, but I am looking for a cross-platform solution.
My question is basically identical to this one, but the answer there is over 10 years old and it doesn't seem to work anymore. I put that code in my program at various positions (in a closeEvent handler, in another function that I called manually just to test it, etc.) and it doesn't flush the clipboard.
My test code is basically identical to that from the old question, but updated for PyQt5:
import sys
import random
from PyQt5 import QtGui, QtWidgets, QtCore
print("Qt Version", QtCore.QT_VERSION_STR)
print("PyQt Version", QtCore.PYQT_VERSION_STR)
app = QtWidgets.QApplication(sys.argv)
edit = QtWidgets.QLineEdit()
edit.setText('try copying this random number {}'.format(random.randint(1, 1000)))
edit.show()
app.exec_()
If I run this and copy the text from the QLineEdit, then close the app, I can't paste the data anywhere; it's gone. If I run it, copy the text, paste it into another app (before closing my PyQt5 test program) and then close my test program, I get strange and inconsistent behavior where I can paste into some apps but not others. It seems I can usually continue to paste into whatever app I pasted into before closing my test program, but pasting into other apps is hit or miss. But the bottom line is that I want pasting to always work into any app regardless of when I closed my Qt program relative to the paste and Qt isn't making that work.
Is there any cross-platform way to force Qt to stop storing "pointers" to clipboard data and to immediately put the actual copied data into the actual system clipboard? I would prefer not to rely on something like closeEvent but to instead completely disable whatever fancy stuff Qt is doing and have it always immediately put the actual data directly into the system clipboard on every clipboard event without ever maintaining any kind of control or pointer handling (so even if I force-killed my Qt app and it didn't get to "clean up" and flush the clipboard on exit, the data would still be on the clipboard). I'm testing this on Windows but I want a solution that works for at least Windows, Mac and Linux.
Related
I am developing an application in Python 3.5, using PyQt4, and I want to test it with unit test using QTest. So far I managed to do whatever I want with QTest except for this problem :
My window as a folder button, when you click it, a File Dialog open to choose a folder (classic). This is (more or less) written like that in my code :
self.file_dialog = QtGui.QFileDialog()
[...]
tmp_path = self.file_dialog.getOpenFileName(self, caption='toto', filter="*.csv")
My problem is that in QTest, I can't find a way to close this dialog when it shows up.
I already tried calling its close() or reject() method (directly or with a single shot timer), but none of these seems to work...
Is there any solution I didn't thought of ? I wouldn't mind closing all windows if that's necessary (but I can't do that either)
Thanks !
As far I have understood, you should not use the static methods (such as getOpenFileName) in tests, because you cannot control the opening of the dialog window. You should instead use the constructor, set the options you need and then call self.file_dialog.exec_() only in the real code (not in the tests).
I am developing an application which uses treeview. Initially, I used Qt designer for the GUI and after, compiled the ui file into python. Until now everything was just fine. Now I want to copy and paste the file on pressing Copy and Paste buttons simultaneously.
I watched and read many tutorials but they used re implementation of QPushButton. I can't adopt this technique because I used designer to create GUI and cant make changes in that file. Please help me to figure out that how can i use QEvents of my treeview.
I hope my question is clear.
This is complex to explain, I hope this will not end up being a vague question getting vague answers.
If this is not the right place to ask this, you may help me to find the proper one.
I have a plugin for Photoshop based on the Listener, so it captures any input from the user.
The plugin creates a python module (called here "ps") containing basically the hInstance and the hwnd of the photoshop window.
Then this plugin, using plain python commands in the plugin for the module like those
PyRun_SimpleString("import Photoshop");
PyRun_SimpleString("Photoshop.showTools()");
will load a special module (here called "Photoshop") that will initialize pyqt and using the QtWinMigrate and the ps module to get the hInstance like this: QMfcApp.pluginInstance(ps.GetPluginInstance()), will start pyqt in photoshop. Here an example code of the Photoshop module using the ps module:
from PyQt4.QtWinMigrate import QMfcApp
from PyQt4.QtGui import QPushButton
import ps #this is implemented in the photoshop plugin (based on the Listener plugin)
#create the plugin instance here
app=QMfcApp.pluginInstance(ps.GetPluginInstance())
def showTools():
box = QPushButton()
box.show()
app.exec_()
Again then, the sequence is like this:
When the plugin starts in photoshop "ps" module is created, then it will load the "Photoshop" module that will load and bind properly pyqt. In the "Photoshop" module I can load any python module, widgets are properly working and everything works really well inside Photoshop.
But now the problem is: using Wacom tablets in Photoshop loose stroke sensitivity, the driver works and everything else works but the pressure sensitivity.
Apparently QMfcApp.pluginInstance will install an event filter to drive the Qt event loop while photoshop still owns the event loop. ( http://doc.qt.digia.com/solutions/4/qtwinmigrate/qmfcapp.html )
and on the paper looks fine to me.. but I could not manage to solve this by myself and I tried, more or less carefully, different approaches:
the listener plugin is not the problem. If Listener plugin runs but python is not initialized sensitivity works fine.
python itself is not a problem. If the listener starts python without gui nor pyqt, then works fine.
as soon as I call pluginInstance which should create the QApplication the issue starts and pressure is lost from the tablet. Even with the small code I wrote before.
Someone may have put pyqt as a plugin somewhere else, since the only purpose of QMfcApp is apparently this one. There is something I can configure to make it work? Is a known issue?
I would rather keep the approach (instead of connecting to photoshop externally like with COM)
I am not able to post the entire code here but let me know if you need something.. I probably can show more.
Thanks a lot for your help
I want to make a QT4 (using QT designer) dialog, that contains a part where a file has to be selected.
Now, I know QFileDialog exists, and I can program something that does what I want.
But can I also just do it in QT designer?
Is there some way to get a "file select" widget in QT designer?
Or, I remember these buttons, having the selected file as a title and a little arrow allowing the user to select another file by the QFileDialog?
So is there a ready made solution, or do I have to program it myself?
There is no file dialog available from the Qt designer as far as I know. But you can easily do it with a few lines of code.
Assuming you have a simple button called pushButton and the path should be stored in lineEdit.
def selectFile():
lineEdit.setText(QFileDialog.getOpenFileName())
pushButton.clicked.connect(selectFile)
[edit]Just wondering though, are you using KDE by any chance? If so, than you can use the KUrlRequester for this. It can easily be configured to support anything from files to urls to directories.
QFileDialog exists in QtGui. At least in my version 4.4 and probably much earlier too. I think the reason it is not in Designer is because it opens its own window instead of being a widget to place on another window.
The documentation from QTDesigner could be better and at least hint of its existence.
Instantiate it and run the show command. It comes right up and defaults to /.
import QtGui
self.fileDialog = QtGui.QFileDialog(self)
self.fileDialog.show()
You can use method getOpenFileName() in QFileDialog Class.
QFileDialog.getOpenFileName() will return the file path and the selected file type
I got this : ('C:/Users/Sathsara/Desktop/UI/Test/test.py', 'All Files (*)')
To get only the file path use QFileDialog.getOpenFileName()[0]
Sample code:
def selectFile():
print(QFileDialog.getOpenFileName()[0])
dlg.locationBtn.clicked.connect(selectFile)
The standalone flashplayer takes no arguments other than a .swf file when you launch it from the command line. I need the player to go full screen, no window borders and such. This can be accomplished by hitting ctrl+f once the program has started. I want to do this programmatically as I need it to launch into full screen without any human interaction.
My guess is that I need to some how get a handle to the window and then send it an event that looks like the "ctrl+f" keystroke.
If it makes any difference, it looks like flashplayer is a gtk application and I have python with pygtk installed.
UPDATE (the solution I used... thanks to ypnos' answer):
./flashplayer http://example.com/example.swf & sleep 3 && ~/xsendkey -window "Adobe Flash Player 10" Control+F
You can use a dedicated application which sends the keystroke to the window manager, which should then pass it to flash, if the window starts as being the active window on the screen. This is quite error prone, though, due to delays between starting flash and when the window will show up.
For example, your script could do something like this:
flashplayer *.swf
sleep 3 && xsendkey Control+F
The application xsendkey can be found here: http://people.csail.mit.edu/adonovan/hacks/xsendkey.html
Without given a specific window, it will send it to the root window, which is handled by your window manager. You could also try to figure out the Window id first, using xprop or something related to it.
Another option is a Window manager, which is able to remember your settings and automatically apply them. Fluxbos for example provides this feature. You could set fluxbox to make the Window decor-less and stretch it over the whole screen, if flashplayer supports being resized. This is also not-so-nice, as it would probably affect all the flashplayer windows you open ever.
I've actually done this a long time ago, but it wasn't petty. What we did is use the Sawfish window manager and wrote a hook to recognize the flashplayer window, then strip all the decorations and snap it full screen.
This may be possible without using the window manager, by registering for X window creation events from an external application, but I'm not familiar enough with X11 to tell you how that would be done.
Another option would be to write a pygtk application that embedded the standalone flash player inside a gtk.Socket and then resized itself. After a bit of thought, this might be your best bet.
nspluginplayer --fullscreen src=path/to/flashfile.swf
which is from the [http://gwenole.beauchesne.info//en/projects/nspluginwrapper](nspluginwrapper project)
Another option would be to write a pygtk application that embedded the standalone flash player inside a gtk.Socket and then resized itself. After a bit of thought, this might be your best bet.
This is exactly what I did. In addition to that, my player scales flash content via Xcomposite, Xfixes and Cairo. A .deb including python source be found here:
http://www.crutzi.info/crutziplayer
I've done this using openbox using a similar mechanism to the one that bmdhacks mentions. The thing that I did note from this was that the standalone flash player performed considerably worse fullscreen than the same player in a maximised undecorated window. (that, annoyingly is not properly fullscreen because of the menubar). I was wondering about running it with a custom gtk theme to make the menu invisible. That's just a performance issue though. If fullscreen currently works ok, then it's unneccisarily complicated. I was running on an OLPC XO, performance is more of an issue there.
I didn't have much luck with nspluginplayer (too buggy I think).
Ultimately I had the luxury of making the flash that was running so I could simply place code into the flash itself. By a similar token, Since you can embed flash within flash, it should be possible to make a little stub swf that goes fullscreen automatically and contains the target sfw.
You have to use Acton script 3 cmd:
stage.displayState = StageDisplayState.FULL_SCREEN;
See Adobe Action script 3 programming.
But be careful : in full screen, you will lose display performances!
I've got this problem ... more under Linux!!!