I'm having issues with cx_freeze relative path logic on mac. I'm using python 3.3 and pyqt5 and building an app portable windows - mac.
The following simple script just loads an image into a QLabel as a QPixmap.
The code works fine both on windows and mac when launched from console, builds both on windows and mac.
The exe works on windows without any problem.
The app ( MacOSX ) does not load the image, same for the dmg.
I have a feeling it has something to do with relative path setting. The reason for this belief is the following:
- if I try to load the .app the image will not appear
- if I copy-paste the testimage.jpeg in the same folder where the .app is it will load the image.
I did try include_files in the setup with no results.
Can anyone help?
Here are the scripts:
First the file image_insert_test.py:
import sys
from PyQt5.QtWidgets import (QApplication, QDialog,
QErrorMessage, QLabel, QWidget, QVBoxLayout )
from PyQt5.QtCore import pyqtSlot, QDir, Qt
from PyQt5 import QtGui
class Window(QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.fill_box2 = QLabel()
pixmap = QtGui.QPixmap('testimage.jpeg')
self.fill_box2.setPixmap(pixmap.scaled(100,100,Qt.KeepAspectRatio))
# set the layout
layout = QVBoxLayout()
layout.addWidget(self.fill_box2)
self.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = Window()
main.setWindowTitle('test gui')
main.show()
sys.exit(app.exec_())
the file setup.py:
import sys
from cx_Freeze import setup, Executable
base = None
if sys.platform == 'win32':
base = 'Win32GUI'
options = {
'build_exe': {
"includes": ["matplotlib.backends.backend_macosx"] ,
"include_files" : ["testimage.jpeg"]
}
}
executables = [
Executable('image_insert_test.py', base=base)
]
setup(name='image_insert_test',
version='0.1',
description='Sample image_insert_test script',
options=options,
executables=executables
)
and this is the log of the cx_freeze bdist_mac http://pastebin.com/77uU4Exr
a workaround is the following:
instead of
pixmap = QtGui.QPixmap('testimage.jpeg')
place:
pixmap = QtGui.QPixmap(os.path.join(os.getcwd(),'image_insert_test-0.1.app/Contents/MacOS','testimage.jpeg')
this fishes the image path from the .app package but there has to be a more elegant way to do it.
Related
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'C:\Users\Χρήστος\Desktop\Papinhio player\project\main\ui files\Menu 1\Sound files\Import sound file\Loading image\loading.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QMovie
class Ui_dialog(object):
def setupUi(self, dialog):
dialog.setObjectName("dialog")
dialog.resize(430, 110)
self.horizontalLayout = QtWidgets.QHBoxLayout(dialog)
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(197, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.label = QtWidgets.QLabel(dialog)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
spacerItem1 = QtWidgets.QSpacerItem(197, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.movie = QMovie("ajax-loader.gif")
self.label.setText("")
self.label.setMovie(self.movie)
#self.label.setScaledContents(True)
self.movie.start()
self.label.resize(220,19)
self.retranslateUi(dialog)
QtCore.QMetaObject.connectSlotsByName(dialog)
def retranslateUi(self, dialog):
_translate = QtCore.QCoreApplication.translate
dialog.setWindowTitle(_translate("dialog", "Εισαγωγή αρχείου ήχου"))
#self.label.setText(_translate("dialog", "123456789101112131415"))
#import main_icons_rc
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
dialog = QtWidgets.QDialog()
ui = Ui_dialog()
ui.setupUi(dialog)
dialog.show()
sys.exit(app.exec_())
The above code works in ubuntu 20.04, but it doesn't appeared something (just only the window, with title and ?,X buttons) in Windows 10.
In Ubuntu i have python3.6
In Windows 10 i have python3.8
What's wrong?
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.addLibraryPath(r"C:\Users\Χρήστος\AppData\Local\Programs\Python\Python38\Lib\site-packages\pyqt5_tools\Qt\plugins")
dialog = QtWidgets.QDialog()
ui = Ui_dialog()
ui.setupUi(dialog)
dialog.show()
sys.exit(app.exec_())
I had to import the image libraries to work!!!
How to run command prompt inside tkinter frame? I know how to do it with "pygame", but those methods doesn't work - command prompt just runs in another window.
I tried to do it like this:
import tkinter as tk
import os
import subprocess
root = tk.Tk()
root.geometry("640x480")
frame = tk.Frame(root)
frame.pack(fill="both", expand=True)
child_env = dict(os.environ)
child_env["SDL_WINDOWID"] = str(frame.winfo_id())
child_env["SDL_VIDEODRIVER"] = "windib"
p = subprocess.Popen(["cmd.exe"], env=child_env)
root.mainloop()
But, as i said, it doesn't work.
This does not use "Command Prompt" as in the program included with Windows, but ConEmu has an -insidewnd parameter which is meant for allowing it to be embedded in third-party applications.
import sys,pathlib,subprocess
import tkinter as tk
import tkinter.ttk as ttk
# assuming a common location for the portable conemu installation:
conemu_exe = pathlib.Path.home()/"Documents"/"ConEmu"/"ConEmu64.exe"
class app(tk.Tk):
def __init__(self):
super().__init__()
self.console_frame = ttk.Frame(self,height=480,width=640)
self.console_frame.pack(fill="both",expand=True)
hwnd = hex(self.console_frame.winfo_id())
p = subprocess.Popen(
[str(conemu_exe), "-insidewnd", hwnd],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
app().mainloop()
from tkinter import Tk, Text
import subprocess
def execute(code):
command = cmd.get('1.0', 'end').split('\n')[-2]
if command == 'exit':
exit()
cmd.insert('end', f'\n{subprocess.getoutput(command)}')
main = Tk()
cmd = Text(main)
cmd.pack()
cmd.bind('<Return>', execute)
main.mainloop()
I have seen many examples of how to show images in Tkinter using an image URL but none of those examples are working for me i.e.
import urllib
from Tkinter import *
import io
from PIL import Image, ImageTk
app = Tk()
app.geometry("1000x800")
im = None #<-- im is global
def search():
global im #<-- declar im as global, so that you can write to it
# not needed if you only want to read from global variable.
tx1get = tx1.get()
Label(app, text="You Entered: \"" + tx1get + "\"").grid(row=1, column=0)
fd = urllib.urlopen("http://ia.media-imdb.com/images/M/MV5BMTc2MTU4ODI5MF5BMl5BanBnXkFtZTcwODI2MzAyOA##._V1_SY317_CR7,0,214,317_AL_.jpg")
imgFile = io.BytesIO(fd.read())
im = ImageTk.PhotoImage(Image.open(imgFile))
image = Label(app, image = im, bg = "blue")
image.grid(row=2, column=0)
tx1=StringVar()
tf = Entry(app, textvariable=tx1, width="100")
b1 = Button(app, text="Search", command=search, width="10")
tf.grid(row=0, column=0)
b1.grid(row=0, column=1)
app.mainloop()
When I run this I get the error "No module name PIL" And in this one:
from io import BytesIO
import urllib
import urllib.request
import tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
url = "http://imgs.xkcd.com/comics/python.png"
with urllib.request.urlopen(url) as u:
raw_data = u.read()
im = Image.open(BytesIO(raw_data))
image = ImageTk.PhotoImage(im)
label = tk.Label(image=image)
label.pack()
root.mainloop()
I get "No module name request" Nearly all examples make use of the PIL module among others, but I cannot get them to work because Python 2.7 doesn't recognize many of them. I need to display an image as a part of an assessment and while we can import things such as Tkinter, the file needs to run without having to add modules from outside the standard Python library.
It is worth noting as well that I can't even import "tkinter". It will say there is no module named "tkinter" because it needs to start with a capital "T".
So my questions are:
Does PIL need me to install additional software/libraries
Does the importation of "tkinter" without the capital "T" not work because I am using Python 2.7?
Using Python 2.7 how do I display an image in a Tkinter window from a URL
This works, using python 2.7 on windows:
from io import BytesIO
import Tkinter as tk
import urllib # not urllib.request
from PIL import Image, ImageTk
root = tk.Tk()
url = "http://imgs.xkcd.com/comics/python.png"
u = urllib.urlopen(url)
raw_data = u.read()
u.close()
im = Image.open(BytesIO(raw_data))
image = ImageTk.PhotoImage(im)
label = tk.Label(image=image)
label.pack()
root.mainloop()
To answer your questions:
You need to install PIL (it's not standard on Python 2.7).
Yes, you need to import Tkinter in Python 2.7; tkinter is for Python 3.x
You can use the code above (provided you install PIL).
Also,
In Python 2.7 you need urllib and not urllib.request
Seems you can't use with....open(x) as fnamein urllib so you need to open and close the file explicitly.
I'm trying to make a gui (Qt Designer) to import an excel file and display the data in the gui.
The script works fine when I run it from within my IDE (Spyder), but if I run it from the command window or by opening the python file from windows explorer, the import function does not work. (The gui starts up fine but when the import button is pressed and the file is selected, nothing happens and no error is produced. When running from Spyder, the data is imported and displayed in the gui as expected).
If I pre-select the file location (commented out in the code below), then the script works fine from the command line or by clicking from explorer.
Thanks for any help!
Python 2.7 (Anaconda), Windows 10, PyQt4
import sys
from PyQt4 import QtGui
from excel_import_gui import Ui_MainWindow
import xlrd
class Main(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setupSignals()
def set_import_data(self,data_to_import,table_to_change):
for row in range(len(data_to_import)):
for col in range(len(data_to_import[0])):
table_to_change.setRowCount(len(data_to_import))
table_to_change.setColumnCount(len(data_to_import[0]))
item = data_to_import[row][col]
table_to_change.setItem(row,col,QtGui.QTableWidgetItem(str(item)))
def setupSignals(self):
self.ui.importData_btn.clicked.connect(self.select_file)
def select_file(self):
excel_file = QtGui.QFileDialog.getOpenFileName(self,
"Select Excel file to import","","Excel (*.xls *.xlsx)")
# excel_file = "C:/Users/Ben/Work/Python tests/Qt GUIs/Excel_import_GUI/fish_test.xlsx"
if excel_file:
open_excel_file = xlrd.open_workbook(excel_file)
self.start_import_data(open_excel_file)
def start_import_data(self, workbook):
#import data from excel file
workbook_data = []
for sheetNum in range (workbook.nsheets):
worksheet = workbook.sheet_by_index(sheetNum)
workbook_data.append([[worksheet.cell_value(row,col) for col in range (worksheet.ncols)] for row in range(worksheet.nrows)])
# Set each worksheet of workbook_data to each tab in GUI widget
self.set_import_data(workbook_data[0],self.ui.fish_table)
self.set_import_data(workbook_data[1],self.ui.boats_table)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
Well I found a solution myself by converting the excel_file variable to a string.
excel_file = str(QtGui.QFileDialog.getOpenFileName(self, "Select Excel file to import","","Excel (*.xls *.xlsx)"))
I'm using Qt.Gui.QFileDialog.getOpenFileName method to open a file. If I set the default file directory to "/Users/me/Documents/data/2013/today/" the dialog box opens to "/Users/me/Documents/data/2013/" with the "today" folder selected. How do I get the the correct default folder to be opened in the window?
fname = QtGui.QFileDialog.getOpenFileName(self, 'Open file', "/Users/me/Documents/data/2012/20121102/images/",'*.npy')
Opens a dialog box in /Users/me/Documents/data/2012/20121102. I want the window to open in /Users/me/Documents/data/2012/20121102/images/
The most probable reason is that the file doesn't exist at the time you are requesting it be opened. For opening folders use QtGui.QFileDialog.getExistingDirectory:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.pushButtonOpen = QtGui.QPushButton(self)
self.pushButtonOpen.setText("Open Folder")
self.pushButtonOpen.clicked.connect(self.on_pushButtonOpen_clicked)
self.layoutHorizontal = QtGui.QHBoxLayout(self)
self.layoutHorizontal.addWidget(self.pushButtonOpen)
#QtCore.pyqtSlot()
def on_pushButtonOpen_clicked(self):
folderName = QtGui.QFileDialog.getExistingDirectory(
self, "Open Directory",
"/path/to/folder",
QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontResolveSymlinks,
)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
sys.exit(app.exec_())
For someone's information (even though 8 years passed)
You could pass the directory argument to getOpenFileName for the default folder in PyQt5.