I'm trying make an exe application from my scripts using py2exe. The problem is that if I run it by doubleclicking on exe file, it closes immediately after open. If I run it from cmd, it works perfect.
I've tried to make a table global but it did not helped. I've already tried to keep the reference - no effect.
Here is the code of GUI in case it helps:
from PyQt4.QtGui import QTableWidget, QTableWidgetItem,QApplication
import sys
from PyQt4.QtGui import *
import os
from meteo import mesiac,den
class MyTable(QTableWidget):
def __init__(self, data, *args):
QTableWidget.__init__(self, *args)
self.data = data
self.setmydata()
self.resizeColumnsToContents()
self.resizeRowsToContents()
def setmydata(self):
horHeaders = []
for n, key in enumerate(['max teplota','min teplota','max vlhkost','min vlhkost','max tlak',
'min tlak','avg teplota','avg vlhkost','avg tlak']):
horHeaders.append(key)
for m, item in enumerate(self.data[key]):
newitem = QTableWidgetItem(str(item))
self.setItem(m, n, newitem)
self.setHorizontalHeaderLabels(horHeaders)
vertical_headers = ['{}.'.format(x+1) for x in xrange(len(self.data.values()[0])-1)]+['Mesiac:']
self.setVerticalHeaderLabels(vertical_headers)
self.setWindowTitle('Meteo')
def show_table():
global table
table = MyTable(data, len(data.values()[0]), len(data.keys()))
table.setFixedHeight(len(data.values()[0])*20)
table.setFixedWidth(len(data.keys())*95)
table.show()
return table
if __name__ == '__main__':
data = {}
os.system("mode con: cols=100 lines=40")
filenames = next(os.walk('mesiac'))[2]
list_of_den = []
for filename in filenames:
list_of_den.append(den(filename,filename[:-4]))
m = mesiac(list_of_den)
for den in list_of_den:
for n,attr in enumerate(['max teplota','min teplota','max vlhkost','min vlhkost','max tlak',
'min tlak','avg teplota','avg vlhkost','avg tlak']):
try:
data[attr].append(den.to_list()[n])
except:
data[attr]=[den.to_list()[n]]
m_list = m.to_list()
for n,attr in enumerate(['max teplota','min teplota','max vlhkost','min vlhkost','max tlak',
'min tlak','avg teplota','avg vlhkost','avg tlak']):
try:
data[attr].append(m_list[n])
except:
data[attr]=[m_list[n]]
app = QApplication(sys.argv)
t = show_table()
sys.exit(app.exec_())
And for sure - here is a setup.py file:
from distutils.core import setup
import py2exe
options ={"py2exe":{"includes":["sip","PyQt4.QtGui","PyQt4.QtCore","meteo"],"dll_excludes": ["MSVCP90.dll", "HID.DLL", "w9xpopen.exe"]}}
setup(window=['table.py'],options=options)
How to make it visible?
Related
I have a simple form where I have a function/method which calls a QFileDialog to choose a file. This form stores the information in a Postgresql database and uses QDataWidgetMapper to map the form fields to database fields. When I add a new row to the model and edit some fields, when I call the QFileDialog, it seems the mappings get removed. All the edited fields on the form go blank. If I go back to a record which was retrieved from the database, I have no problems adding the image as the data persists on the form.
It seems to be related to the submit = self.c_mapper.submit() line of code. When I comment this out, the data persists in the form but I also can’t get the query().LastInsertId().
When stepping through the code, the form field data disappears when if dlg.exec_() == QDialog.Accepted: line is reached.
The desired behaviour is to be able to call the function which selects the image file and continue editing the same record with the correct data in the fields.
See the animation:
See the code:
import sys
import os
from pathlib import Path
import shutil
#PyQt stuff
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *
from PyQt5.QtWidgets import *
#form modules
from form import *
class Contact(QMainWindow):
def __init__(self, cont_id, parent=None):
QMainWindow.__init__(self)
self.cont_id = cont_id
self.ui = Ui_contact_form()
self.ui.setupUi(self)
self.c_model = QSqlTableModel(self)
self.c_model.setTable("contacts")
self.c_model.select()
self.row = self.c_model.rowCount()
self.c_model.insertRow(self.row)
self.setWindowTitle('New contact')
self.c_mapper = QDataWidgetMapper(self)
self.c_mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
self.c_mapper.setModel(self.c_model)
#self.c_mapper.setItemDelegate(QSqlRelationalDelegate(self))
self.c_mapper.addMapping(self.ui.title, self.c_model.fieldIndex("title"))
self.c_mapper.addMapping(self.ui.first_name, self.c_model.fieldIndex("first_name"))
self.c_mapper.addMapping(self.ui.last_name, self.c_model.fieldIndex("last_name"))
self.c_mapper.addMapping(self.ui.nickname, self.c_model.fieldIndex("nickname"))
self.c_mapper.addMapping(self.ui.job_title, self.c_model.fieldIndex("job_title"))
self.c_mapper.addMapping(self.ui.birth_date, self.c_model.fieldIndex("birth_date"))
self.c_mapper.addMapping(self.ui.website, self.c_model.fieldIndex("website"))
self.c_mapper.addMapping(self.ui.comments, self.c_model.fieldIndex("comments"))
self.c_mapper.addMapping(self.ui.users, self.c_model.fieldIndex("user_name"))
self.c_mapper.addMapping(self.ui.tags, self.c_model.fieldIndex("tags"))
self.c_mapper.setCurrentIndex(self.row)
self.ui.get_image_file.clicked.connect(self.get_profile_image)
def get_profile_image(self):
submit = self.c_mapper.submit()
self.cont_id = self.c_model.query().lastInsertId()
data_loc = Path('/home/dave/hd/Nextcloud/crm_data/')
database = 'crm'
dlg = QFileDialog(self)
dlg.setFileMode(QFileDialog.AnyFile)
home = os.path.expanduser('~') + "/Downloads"
dlg.setDirectory(home)
if dlg.exec_() == QDialog.Accepted:
selected_file = dlg.selectedFiles()[0]
else:
return
selected_file = Path(selected_file)
ext = selected_file.suffix
ext = ext.lower()
target_loc = data_loc / database / "contacts/images"
target_file = str(self.cont_id) + ext
target_dest = target_loc / target_file
shutil.move(str(selected_file), str(target_dest))
self.ui.image.setPixmap(QPixmap(str(target_dest)).scaled(self.ui.image.size(),Qt.KeepAspectRatio))
if __name__=="__main__":
app=QApplication(sys.argv)
db = QSqlDatabase.addDatabase("QPSQL");
db.setHostName('hostname')
db.setDatabaseName('crm')
db.setUserName('usr')
db.setPassword('pw')
if (db.open()==False):
QMessageBox.critical(None, "Database Error", db.lastError().text())
myapp = Contact('')
myapp.show()
sys.exit(app.exec_())
I tried following this answer: How to use PyQT5 to convert multiple HTML docs to PDF in one loop
I modified it to convert all html files found in a local folder. For example htmls is a list of html files to be converted: [Q:\Ray\test1.html, Q:\Ray\prac2.html]
This is the code. However, when I try to run it, Python just freezes and I have to stop the run.
import os
import glob
from PyQt5 import QtWidgets, QtWebEngineWidgets
class PdfPage(QtWebEngineWidgets.QWebEnginePage):
def __init__(self):
super().__init__()
self._htmls = []
self._current_path = ""
self.setZoomFactor(1)
self.loadFinished.connect(self._handleLoadFinished)
self.pdfPrintingFinished.connect(self._handlePrintingFinished)
def convert(self, htmls):
self._htmls = iter(zip(htmls))
self._fetchNext()
def _fetchNext(self):
try:
self._current_path = next(self._htmls)
except StopIteration:
return False
def _handleLoadFinished(self, ok):
if ok:
self.printToPdf(self._current_path)
def _handlePrintingFinished(self, filePath, success):
print("finished:", filePath, success)
if not self._fetchNext():
QtWidgets.QApplication.quit()
if __name__ == "__main__":
current_dir = os.path.dirname(os.path.realpath(__file__))
folder= current_dir+ '\\*.HTML'
htmls= glob.glob(folder)
app = QtWidgets.QApplication([])
page = PdfPage()
page.convert(htmls)
app.exec_()
print("finished")
It seems that the OP has not understood the logic of my previous solution which is:
Get the resource, in this case files,
Load it on the page,
When the load is finished then print the content of the page,
When the printing is finished then execute step 1 with the next resource.
In this it does not perform step 2, on the other hand it is recommended that the path of the pdf has a name other than the html
import os
import glob
from PyQt5.QtCore import QUrl
from PyQt5 import QtWidgets, QtWebEngineWidgets
class PdfPage(QtWebEngineWidgets.QWebEnginePage):
def __init__(self):
super().__init__()
self._htmls = []
self._current_path = ""
self.setZoomFactor(1)
self.loadFinished.connect(self._handleLoadFinished)
self.pdfPrintingFinished.connect(self._handlePrintingFinished)
def convert(self, htmls):
self._htmls = iter(htmls)
self._fetchNext()
def _fetchNext(self):
try:
self._current_path = next(self._htmls)
except StopIteration:
return False
else:
self.load(QUrl.fromLocalFile(self._current_path))
return True
def _handleLoadFinished(self, ok):
if ok:
self.printToPdf(self._current_path + ".pdf")
def _handlePrintingFinished(self, filePath, success):
print("finished:", filePath, success)
if not self._fetchNext():
QtWidgets.QApplication.quit()
if __name__ == "__main__":
current_dir = os.path.dirname(os.path.realpath(__file__))
folder= current_dir+ '\\*.HTML'
htmls = glob.glob(folder)
print(htmls)
if htmls:
app = QtWidgets.QApplication([])
page = PdfPage()
page.convert(htmls)
app.exec_()
print("finished")
I have two python files, the first one is to handle database related stuff and the second one imports that file so I can use it with PyQt.
The problem is if I want to change the label in the first file it doesn't work the application just crashes.
The reason I want the first file to be able to change the label is if an error occurs when trying to connect to the DB.
Here is a short view of my code:
First file.
from mysql.connector import (connection)
from datetime import *
from RPI1_ui import Ui_Form
'''Handling of database related stuff'''
class DatabaseUtility(Ui_Form):
def __init__(self):
#DB Connection
self.cnx = None
self.cursor = None
def mysql_connect(self):
# Database connection
try:
self.cnx = connection.MySQLConnection(user='root', password='', host='127.0.0.1', database='spicadb')
self.cursor = self.cnx.cursor()
except connection.errors.InterfaceError as e:
self.lblShowInfo.setText(str(e)) # -> Try to change label
def get_table(self):
return self.run_command("SELECT * FROM tblseal")
def get_columns(self):
return self.run_command("SHOW COLUMNS FROM tblseal")
Second file.
from PyQt5.QtWidgets import QApplication, QWidget, QDialog
from datetime import *
from bs4 import BeautifulSoup as bs
import os
import sys
import DatabaseHandling
'''Convert UI file to Python'''
os.chdir("C:\\Users\Gianni Declercq\AppData\Local\Programs\Python\Python36-32\Scripts")
os.system("pyuic5.exe H:\QtProjects\\RPI1.ui -o H:\QtProjects\\RPI1_ui.py")
from RPI1_ui import Ui_Form # import after recreation of py file
from RPI1_Sec import SecondWindow
'''Main program'''
class MainWindow(QWidget, Ui_Form):
def __init__(self):
super(MainWindow, self).__init__()
# Initialize variables
self.dbu = DatabaseHandling.DatabaseUtility()
self.spica_reference = None
self.barcode = None
self.msl = None
self.package_body = None
self.window2 = None
# Get UI elements + resize window
self.setupUi(self)
self.resize(800, 480)
# Define what should happen on button click
self.btnQuit.clicked.connect(lambda: app.exit())
self.btnInsert.clicked.connect(lambda: self.get_entry())
self.btnTable.clicked.connect(lambda: self.new_window())
# Style buttons
self.btnQuit.setStyleSheet("background-color: red")
self.btnInsert.setStyleSheet("background-color: green")
self.btnTable.setStyleSheet("background-color: orange")
def get_entry(self):
try:
self.spica_reference = self.txtReferentie.text()
self.barcode = self.txtBarcode.text()
self.msl = self.txtMsl.text()
self.package_body = float(self.txtBodyPackage.text())
except ValueError:
self.lblShowInfo.setText("Please insert the correct values")
self.lblShowInfo.setStyleSheet('color: red')
else:
self.dbu.mysql_connect()
if self.dbu.cursor and self.dbu.cnx is not None:
self.dbu.add_entry(self.spica_reference, self.barcode, self.msl, self.package_body, self.calc_floor_life)
Give a "hook function" to the DatabaseUtility when initializing.
class MainWindow(QWidget, Ui_Form):
def __init__():
def ch_lab(text):
self.lblShowInfo.setText(text)
self.dbu = DatabaseHandling.DatabaseUtility(ch_lab)
class DatabaseUtility(Ui_Form):
def __init__(cb):
self.error_warn = cb
#.. error happening
self.error_warn('error')
I'm trying to append nodes of namedtuple object to a treeView but I'm not sure how to subclass QAbstractItem (if that's even the proper way). I'm still very new to Python so this is confusing to me. Here is my problem code:
Exercise = namedtuple('Exercise','name html list')
e_list = []
for i in range(1,6,1):
dummy_list = [1,2,3,'a','b','c']
ntup = Exercise("exercise{0}".format(i),'html here',dummy_list)
e_list.append(ntup)
for e in e_list:
item = QtGui.QStandardItem(e) # gives error
self.tree_model.appendRow(item) # doesnt execute
And here is the the whole program:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from collections import namedtuple
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.pushButton = QtGui.QPushButton(self)
self.pushButton.setText("Test 1 - doesn't work")
self.pushButton.clicked.connect(self.on_pushbutton)
self.pushButton2 = QtGui.QPushButton(self)
self.pushButton2.setText("Test 2 - works")
self.pushButton2.clicked.connect(self.on_pushbutton2)
self.treeView = QtGui.QTreeView(self)
self.treeView.clicked[QModelIndex].connect(self.on_clickitem)
self.tree_model = QtGui.QStandardItemModel()
self.treeView.setModel(self.tree_model)
self.layoutVertical = QtGui.QVBoxLayout(self)
self.layoutVertical.addWidget(self.pushButton)
self.layoutVertical.addWidget(self.pushButton2)
self.layoutVertical.addWidget(self.treeView)
def on_pushbutton(self):
Exercise = namedtuple('Exercise','name html list')
e_list = []
for i in range(1,3,1):
dummy_list = [1,2,3,'a','b','c']
ntup = Exercise("exercise{}".format(i),'html here',dummy_list)
e_list.append(ntup)
for e in e_list:
item = QtGui.QStandardItem(e) # gives error
self.tree_model.appendRow(item) # never occurs
def on_pushbutton2(self):
txt = 'hello world'
item = QtGui.QStandardItem(txt)
self.tree_model.appendRow(item)
def on_clickitem(self,index):
item = self.tree_model.itemFromIndex(index) # doesn't work
print "item name:",item.getName() # doesn't work
print "item html:",item.getHtml() # doesn't work
print "item list:",item.getList() # doesn't work
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
sys.exit(app.exec_())
I want to append the nodes into a tree and when I click on an item I want to get the values of the namedtuple (i.e. the values of 'name', 'html', and 'alist'). Thanks for your help.
Paul
I just ended up using QTreeWidget and setting the tree item data like this:
item = QtGui.QTreeWidgetItem()
item.mydata = my_namedtuple
I found the answer here: QtGui QTreeWidgetItem setData holding a float number
I didn't know you could just dynamically make an attribute for the tree item.
I borrowed this code from another StackOverflow answer:
from PyQt4 import QtCore
#QtCore.pyqtSlot(str)
def directory_changed(path):
print('Directory Changed!!!')
#QtCore.pyqtSlot(str)
def file_changed(path):
print('File Changed!!!')
fs_watcher = QtCore.QFileSystemWatcher(['/path/to/files_1', '/path/to/files_2', '/path/to/files_3'])
fs_watcher.connect(fs_watcher, QtCore.SIGNAL('directoryChanged(QString)'), directory_changed)
fs_watcher.connect(fs_watcher, QtCore.SIGNAL('fileChanged(QString)'), file_changed)
The problem is, file_changed never gets called, no matter what. directory_changed is reliably called when a file is added, for example, but changing the files content does not result in file_changed being called.
I called a few variations of QtCore.SIGNAL('fileChanged(QString)'), eg, QtCore.SIGNAL('fileChanged(const QString &)'), to no avail. There are no warnings, or errors -- it simply does not trigger the function.
Recommendations?
It's hard to be certain what's going wrong, because the example code is incomplete, and so cannot work at all as it stands.
However, assuming the real code you are running is more or less sane/complete, your problem is probably caused by not adding the directory itself to the list of paths.
A basic script should look something like this:
import sys
from PyQt4 import QtCore
def directory_changed(path):
print('Directory Changed: %s' % path)
def file_changed(path):
print('File Changed: %s' % path)
app = QtCore.QCoreApplication(sys.argv)
paths = [
'/path/to',
'/path/to/files_1',
'/path/to/files_2',
'/path/to/files_3',
]
fs_watcher = QtCore.QFileSystemWatcher(paths)
fs_watcher.directoryChanged.connect(directory_changed)
fs_watcher.fileChanged.connect(file_changed)
sys.exit(app.exec_())
import argparse
import configparser
import os
import sys
from PyQt5 import QtCore
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QDesktopWidget, QMessageBox
from PyQt5.QtWidgets import QMainWindow
from ProgressBar_ui import Ui_Form
class ProgressBarWindow(QMainWindow, Ui_Form):
def __init__(self):
super().__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.progressBar.setMinimum(0)
self.ui.progressBar.setMaximum(0)
self.ui.progressBar.setValue(0)
self.setWindowTitle("Progress Bar")
self.MSversion = ""
self.LOADING_LOG_PATH = ""
mainIco = ("Icons\myIcon.ico")
self.setWindowIcon(QIcon(mainIco))
self.ui.label.setText("")
self.ui.label.setWordWrap(True)
def location_on_the_screen(self):
ag = QDesktopWidget().availableGeometry()
sg = QDesktopWidget().screenGeometry()
widget = self.geometry()
x = ag.width() - widget.width()
y = 2 * ag.height() - sg.height() - widget.height()
self.move(x, y)
def file_changed(self, pathPassed):
if os.path.exists(pathPassed):
f = open(pathPassed, "r")
for x in f:
#print(x)
label =x
self.ui.label.setText(label)
if x == "CloseLoading":
self.close()
def main():
app = QApplication(sys.argv)
w = ProgressBarWindow()
w.setWindowFlags(w.windowFlags() & ~QtCore.Qt.WindowMaximizeButtonHint)
parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(description='ProgressBar Arguments')
parser.add_argument('version', action="store", type=str)
args = vars(parser.parse_args())
if len(sys.argv) < 1:
msg = QMessageBox()
msg.setIcon(QMessageBox.Critical)
errorMsg = "There are less than 2 command line arguments provided.\nLauncher can not be run."
msg.setText(errorMsg)
msg.setWindowTitle("Save paths..")
msg.exec_()
sys.exit()
p= '/path/toFile/'
paths = [ p ]
fs_watcher = QtCore.QFileSystemWatcher(paths)
#fs_watcher.directoryChanged.connect(w.directory_changed)
fs_watcher.fileChanged.connect(w.file_changed)
w.location_on_the_screen()
w.show()
app.exec_()
if __name__ == "__main__":
sys.exit(main())