I'm trying to open a specific folder from my PyQt program. I know I could've used webbrowser module
like this
import webbrowser, os
path="C:/Users"
webbrowser.open(os.path.realpath(path))
or I could've used os.startfile module like this
import os
path = "C:/Users"
path = os.path.realpath(path)
os.startfile(path)
or subprocess which isn't recommended on Qt platform. so I wonder how could you do it on PyQt properly (maybe using QProcess?). I don't want to open file or folder dialog because I just want to open the folder without doing anything with it. also, I want to save time for a future update on a different OS than Windows, so I didn't have to change this part. is it possible?. many thanks
A Qt cross-platform solution is to use QDesktopServices::openUrl():
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
app = QtWidgets.QApplication(sys.argv)
path = "C:/Users"
fullpath = os.path.realpath(path)
if not QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(fullpath)):
print("failed")
I managed to use QProcess to open explorer on specific path without additional module (e.g webbrowser). I only need platform module to determine which platform the program is running, like this
self.path = os.path.abspath(os.path.dirname(sys.argv[0]))
self.pathOutput = os.path.join(self.path, "output")
def open_explorer(self):
self._process = QtCore.QProcess(self)
if platform.system() == "Windows":
self._process.start("explorer",[os.path.realpath(self.pathOutput)])
elif platform.system() == "Darwin":
self._process.start("open",[os.path.realpath(self.pathOutput)])
Related
I want to create a hyperlink of (file_path ) using python that will point to the file in operating system. I am able to get the path of the file. How can I create a hyperlink of this path and store in a variable. I want to display this in the QtWidgets as link where user can click and open the file stored in windows OS.
file_path = os.path.join(dir_path, FileName)
self.documents.setItem(0, 0, QtWidgets.QTableWidgetItem(file_path))
You can use QLabel with html content to create clickable link.
from PyQt5 import QtWidgets, QtCore
import os
if __name__ == "__main__":
app = QtWidgets.QApplication([])
path = os.environ["USERPROFILE"]
text = "click me"
label = QtWidgets.QLabel('{}'.format(path, text))
label.show()
label.linkActivated.connect(os.startfile)
app.exec()
I try to build my (fine working) python 3.6 tkinter gui app to a windows excecutable. After hours of trial an error (with some name and dll issues) I got it to run. But it seems to have varoius of bugs. Some functions seem not to work and I have no console output of the produced error... is there a way to debug the exe?
this is my setup.py
import sys
from cx_Freeze import setup, Executable
import os
os.environ['TCL_LIBRARY'] = r'C:\Users\xxx\AppData\Local\Programs\Python\Python36\tcl\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\Users\xxx\AppData\Local\Programs\Python\Python36\tcl\tk8.6'
base = None
if sys.platform == 'win32':
base = 'Win32GUI'
executables = [
Executable('myApp.py', base=base)
]
build_exe_options = {"packages": ["tkinter",
"PIL",
"savReaderWriter",
"numpy",
"scipy",
"os"],
"include_files": ["tcl86t.dll",
"tk86t.dll"]}
setup(name='myApp',
version='0.1',
description='some description',
options = {'build_exe': build_exe_options},
executables=executables
)
myApp.py
is too big to post it here. This is a snippet that only works 'unfreezed'. You need an spss.sav file like this to try this out.
from tkinter import *
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk, ImageDraw
from savReaderWriter import SavReader
import numpy as np
from scipy.ndimage import gaussian_filter
import os
class MyApp:
spss_file = None
def import_spss(self, *args):
filename = filedialog.askopenfilename()
if filename:
try:
with SavReader(filename, returnHeader=True, ioUtf8=True) as reader:
spss_file = reader.all()
self.spss_file = np.array(spss_file)
except Exception as ex:
messagebox.showinfo(title="Import SPSS File",
message="Warning: wrong file format chosen! \nAccepted formats: sav")
print(ex)
return
else:
return
def main():
App = MyApp()
App.import_spss()
print("everything works fine")
main()
if you want the console window to appear, after it is frozen, just remove this code from the setup script:
if sys.platform == 'win32':
base = 'Win32GUI'
what that code does is it tells cx_Freeze to have the console window not show up, after frozen. this is only required on windows, because on other OSes,it depends on whether or not it was run from a terminal. make sure though, when you have finished debugging it, to put that code back in, or the console window will show up in your app.
by the way, one of the most annoying problems I've ever had was when making a program with tkinter and cx_Freeze. the problem was that it was starting in the wrong directory and not able to find the TK Dll. If when you run this with the console, and you see something about a file not found, chances are you are not including it or it is in the wrong directory.
have a good day!
I'm mainly working in Spyder, building scripts that required a pop-up folder or file Browse window.
The code below works perfect in spyder.
In Pycharm, the askopenfilename working well, while askdirectory do nothing (stuck).
But, if running in debug mode - the script works well.
I tried to run the script from SAS jsl - same issue.
Any Idea what should I do?
Python 3.6
Pycharm 2017.2
Thanks.
The Code I'm using includes:
import clr #pythonnet 2.3.0
import os
import tkinter as tk
from tkinter.filedialog import (askdirectory,askopenfilename)
root = tk.Tk()
root.withdraw()
PPath=askdirectory(title="Please select your installation folder location", initialdir=r"C:\Program Files\\")
t="Please select jdk file"
if os.path.exists(os.path.expanduser('~\Documents')):
FFile = askopenfilename(filetypes=(("jdk file", "*.jdk"),("All Files", "*.*")),title=t, initialdir=os.path.expanduser('~\Documents'))
else:
FFile= askopenfilename(filetypes=(("jdk file", "*.jdk"),("All Files", "*.*")),title=t)
sys.path.append(marsDllPath)
a = clr.AddReference('MatlabFunctions')
aObj = a.CreateInstance('Example.MatlabFunctions.MatLabFunctions')
edit: seems like issue related to the pythonnet "imoprt clr", but I do need it in the code.
Similar question asked here: https://github.com/pythonnet/pythonnet/issues/648
Your problem is rather mediocre, although not so obvious. The problem is not in tinker or pythonnet, it stems from the COM threading model.
To begin with, since you're using the clr, let's try to use dialogs directly with it (it's not absolutely necessary to import the tinker module):
# importing pythonnet
import clr
# adding reference (if necessary) to WinForms and importing dialogs
# clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import OpenFileDialog, FolderBrowserDialog
# creating instances of dialogs
folder_dialog = FolderBrowserDialog()
file_dialog = OpenFileDialog()
# try to show any of them
folder_dialog.ShowDialog()
file_dialog.ShowDialog()
As you can see, it hangs just like in your case. The reason, as was mentioned above, stems from the threading's apartment state([1], [2]).
Therefore the clr implicilty sets this state to MTA (Multi-threaded apartment), which can be tested via CoGetApartmentType function:
# importing ctypes stuff
import ctypes
get_apartment = ctypes.windll.ole32.CoGetApartmentType
# comment/uncomment this import to see the difference
# import clr
apt_type = ctypes.c_uint(0)
apt_qualifier = ctypes.c_uint(0)
if get_apartment(ctypes.byref(apt_type), ctypes.byref(apt_qualifier)) == 0:
# APPTYPE enum: https://msdn.microsoft.com/en-us/library/windows/desktop/ms693793(v=vs.85).aspx
# APTTYPEQUALIFIER enum: https://msdn.microsoft.com/en-us/library/windows/desktop/dd542638(v=vs.85).aspx
print('APTTYPE = %d\tAPTTYPEQUALIFIER = %d' % (apt_type.value, apt_qualifier.value))
else:
print('COM model not initialized!')
However, many older COM objects, such as shell dialogs, require STA mode.
Good explanation about the difference between those two states can be found here or there.
Finally, the solutions:
1) Use STA thread for dialogs:
# importing tkinter stuff
import tkinter as tk
from tkinter.filedialog import askdirectory, askopenfilename
# importing pythonnet
import clr
# adding reference (if necessary) to WinForms and importing dialogs
#clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import OpenFileDialog, FolderBrowserDialog
# adding reference (if necessary) to Threading and importing Thread functionality
#clr.AddReference('System.Threading')
from System.Threading import Thread, ThreadStart, ApartmentState
# WinForms thread function example
def dialog_thread():
folder_dialog = FolderBrowserDialog()
file_dialog = OpenFileDialog()
folder_dialog.ShowDialog()
file_dialog.ShowDialog()
# Tk thread function example
def tk_dialog_thread():
root = tk.Tk()
root.withdraw()
askdirectory()
askopenfilename()
# check again apartment state at start
current_state = Thread.CurrentThread.GetApartmentState()
if current_state == ApartmentState.STA:
print('Current state: STA')
elif current_state == ApartmentState.MTA:
print('Current state: MTA')
# start dialogs via CLR
thread = Thread(ThreadStart(dialog_thread))
thread.SetApartmentState(ApartmentState.STA)
thread.Start()
thread.Join()
# start dialogs via Tkinter
thread = Thread(ThreadStart(tk_dialog_thread))
thread.SetApartmentState(ApartmentState.STA)
thread.Start()
thread.Join()
2) Force STA mode via CoInitialize/CoInitializeEx before CLR does so for MTA:
# importing ctypes stuff
import ctypes
co_initialize = ctypes.windll.ole32.CoInitialize
# importing tkinter stuff
import tkinter as tk
from tkinter.filedialog import askdirectory, askopenfilename
# Force STA mode
co_initialize(None)
# importing pythonnet
import clr
# dialogs test
root = tk.Tk()
root.withdraw()
askdirectory()
askopenfilename()
I have tested the code which you pasted on Pycharm 2018.1.3 with python-3.6.5 installed on win-7 64 bit machine. It works fine without any error. There are few bugs in 2017 version. Try upgrading to latest version of Pycharm
This seems simple. I have a Jupyter Notebook with the following code allowing for a file dialog so the user can select a file to analyze. There are a couple of different files used and it is important the user selects the proper file in the proper order. I am trying to add information to the Window title so the user knows which file the script is looking for.
Here is the Notebook code:
import PCB_utility
f_name = PCB_utility.get_file('Select Bitwise data file')
df_bitwise = pd.read_excel(f_name, sheetname = 'lvtemporary_653630', header=(0))
f_name = PCB_utility.get_file('Select ARINC 429 data file')
df_ARINC = pd.read_csv(f_name, sep = '\t', header=(0))
The file dialog works. The user selects the file, and the program just does what it needs to. I am trying to make it a little more user friendly.
PCB_utility looks like this:
import sys
from PyQt4.QtGui import *
#from PyQt4.QtCore import *
def get_file(Instructions):
filename = QFileDialog.getOpenFileName(None, Instructions, '/')
return(filename)
The problem is the Instructions are NOT making through to the dialog box. I manually entered this function into the IPython section and it works beautifully. It doesn't add the extra text when I call it from the notebook. It just has the standard 'Open File'.
Here is the code that finally worked:
import sys
from PyQt4.QtGui import *
def get_file(Instructions):
# Create an PyQT4 application object.
app = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
wid = QWidget()
# Get filename using QFileDialog
filename = QFileDialog.getOpenFileName(wid, Instructions, '/')
return(filename)
sys.exit(app.exec_())
I needed to add the PyQt4 application and widget, then close it. I have to admit I don't quite understand why, but it works.
OP already found solution, but for others that looking for the same thing - you can use IPython magic command for enabling IPython GUI event loop integration, to make working external GUI called from IPython (i.e. Jupyter notebook):
# Magic (we must tell IPython that we will be running an external Qt GUI)
%gui qt5
from PyQt5.QtWidgets import QFileDialog
def select_file(directory='./'):
fname = QFileDialog.getOpenFileName(None,
'Select file...',
directory,
filter='All files (*)')
return fname[0]
As original question is for PyQt4, above command %gui qt5 should be replaced with %gui qt4 or only %gui qt.
To do the same thing without magic commands (similar to OP's solution):
import sys
from PyQt5.QtWidgets import QApplication, QFileDialog
def select_file(directory='./'):
app = QApplication(sys.argv)
fname = QFileDialog.getOpenFileName(None,
'Select file...',
directory,
filter='All files (*)')
return fname[0]
I am trying a couple of sample programs that are not working in the last image of Debian for BBB. They work in a regular Xubuntu 13.10 distribution ad on windows but I have not been able to identify why Qpixmap is not working on this image. The regular widgets work Ok but the Qpixmap is not showing the image. The pyqt version installed is the 4.9.
One of the examples that I am using is the following.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
class Imagen(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout(self)
pixmap = QtGui.QPixmap("test.png")
lbl = QtGui.QLabel(self)
lbl.setPixmap(pixmap)
hbox.addWidget(lbl)
self.setLayout(hbox)
self.move(300, 200)
self.setWindowTitle('Test')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Imagen()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Assuming that your png and python files are in the same directory add the following code:
Import os.path
import os.path as osp
add the following code to initUI()
...
path = osp.join(osp.direname(__file__), 'test.png')
pixmap = QtGui.QPixmap(path)
...
Relative paths are relative to the current directory, which is not necessarily the same as the directory the script itself is in. So either use an absolute pathname, or cd to the directory the image file is in before running the script.
However, if you're interested in solving this general issue properly, the best approach is to learn how to use the Qt Resource System and the pyrcc tool. This allows you to embed icons (or any files you like) directly in your application, and thus completely side-steps any potential problems with locating files.