I am trying to display rich text (or html) in a segment of a wx python frame
I have tried the rtf control with no luck (see here). I am now trying the html route, but in the only examples I can find the html is display in a window that takes over the whole frame; for example from here
import wx
import wx.html
class MyHtmlFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title)
html = wx.html.HtmlWindow(self)
if "gtk2" in wx.PlatformInfo:
html.SetStandardFonts()
html.SetPage(
"Here is some <b>formatted</b> <i><u>text</u></i> "
"loaded from a <font color=\"red\">string</font>.")
app = wx.PySimpleApp()
frm = MyHtmlFrame(None, "Simple HTML")
frm.Show()
app.MainLoop()
Is it possible to display html in a textbox or some other suitable control that I can incorporate into my application?
I want the screen to look like that below. Can the wx.TextCtrl be replaced by an HTML window or something?
import wx
class MainFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title)
panel = MainPanel(self)
panel.txt_comments.SetValue(
"Here is some <b>formatted</b>"
"<i><u>text</u></i> "
"loaded from a "
"<font color=\"red\">string</font>.")
class MainPanel(wx.Panel):
def __init__(self, frame):
wx.Panel.__init__(self, frame)
txt_style = wx.VSCROLL|wx.HSCROLL|wx.TE_READONLY|wx.BORDER_SIMPLE
self.txt_comments = wx.TextCtrl(self, size=(300, 150), style=txt_style)
cmd_update = wx.Button(self, wx.ID_REFRESH)
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(self.txt_comments, flag=wx.ALL, border=10)
main_sizer.Add(cmd_update, flag=wx.ALL, border=10)
self.SetSizerAndFit(main_sizer)
app = wx.App()
frm = MainFrame(None, "Screen layout")
frm.Show()
app.MainLoop()
This must be somewhat close to an utter minimum of code.
#!/usr/bin/env python
import wx
import wx.html as html
#----------------------------------------------------------------------
ID_New = wx.NewId()
ID_Exit = wx.NewId()
#----------------------------------------------------------------------
class MyParentFrame(wx.MDIParentFrame):
def __init__(self):
wx.MDIParentFrame.__init__(self, None, -1, "MDI Parent", size=(600,400))
self.winCount = 0
menu = wx.Menu()
menu.Append(ID_New, "&New Window")
menu.AppendSeparator()
menu.Append(ID_Exit, "E&xit")
menubar = wx.MenuBar()
menubar.Append(menu, "&File")
self.SetMenuBar(menubar)
self.CreateStatusBar()
self.Bind(wx.EVT_MENU, self.OnNewWindow, id=ID_New)
self.Bind(wx.EVT_MENU, self.OnExit, id=ID_Exit)
def OnExit(self, evt):
self.Close(True)
def OnNewWindow(self, evt):
self.winCount = self.winCount + 1
win = wx.MDIChildFrame(self, -1, "Child Window: %d" % self.winCount)
self.html = html.HtmlWindow(win, -1)
self.html.SetPage(
"Here is some <b>formatted</b> <i><u>text</u></i> "
"loaded from a <font color=\"red\">string</font>.")
#----------------------------------------------------------------------
if __name__ == '__main__':
class MyApp(wx.App):
def OnInit(self):
frame = MyParentFrame()
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(False)
app.MainLoop()
I expect the main lines to note are these:
win = wx.MDIChildFrame(self, -1, "Child Window: %d" % self.winCount)
self.html = html.HtmlWindow(win, -1)
self.html.SetPage(
"Here is some <b>formatted</b> <i><u>text</u></i> "
"loaded from a <font color=\"red\">string</font>.")
win is the frame in which you want to house the HTMLWindow.
Notice that win is the first parameter to HTMLWindow.
I used wxWindow quite a bit several years ago, and I've lost most of my skills. Now I remember that the secret to getting a leg up is to start with the demo codes. I used a couple of them this time.
Edit on the basis of comments:
import wx
import wx.html as html
class MainFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title)
panel = MainPanel(self)
class MainPanel(wx.Panel):
def __init__(self, frame):
wx.Panel.__init__(self, frame)
txt_style = wx.VSCROLL|wx.HSCROLL|wx.TE_READONLY|wx.BORDER_SIMPLE
self.html = html.HtmlWindow(self, -1, size=(300, 150), style=txt_style)
self.html.SetPage(
"Here is some <b>formatted</b>"
"<i><u>text</u></i> "
"loaded from a "
"<font color=\"red\">string</font>.")
app = wx.App()
frm = MainFrame(None, "Screen layout")
frm.Show()
app.MainLoop()
wx.html.HtmlWindow or wx.html2.WebView are much like other child widgets in wxPython, in that they need a parent, and the size and position need to be managed in some way, and so on. That also means that you can replace the use of TextCtrl in your sample with one of those widgets, and replace SetValue with SetPage and it should work the way you want. See the docs for specifics and give it a try.
Related
I am trying to develop an interactive wizard in wxPython 4.0(Phoenix) with Python 3.7. Basically the wizard has 4 pages(Stages). Each time I click Next, it should run a different Python script by taking the arguments on the page. I need to display the progress of the running of script on the wizard page.
I have already developed a basic interface for wizard with 4 pages. Now I need help on
1. How to pass arguments from the Page to the Python script?
2. How to call a different Python script everytime I click Next Button on the 4 Pages of wizard? (I think I need to write code around the event ON_PAGE_CHANGING, But I am not clear how to call a different Python script everytime I click NExt Button)
3. How to display progress bar of each script on the wizard?
I am attaching the code for my Basic wizard interface. I am new to WxPython, Any help on the above 3 points is greatly appreciated.
#!/usr/bin/env python
import wx
import wx.adv
from wx.adv import Wizard as wizmod
#import images
from wx.adv import WizardPage, WizardPageSimple
import os.path
padding = 5
class wizard_page(wx.adv.WizardPage):
''' An extended panel obj with a few methods to keep track of its siblings.
This should be modified and added to the wizard. Season to taste.'''
def __init__(self, parent, title):
WizardPage.__init__(self, parent)
self.next = self.prev = None
self.sizer = wx.BoxSizer(wx.VERTICAL)
title = wx.StaticText(self, -1, title)
title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
self.sizer.Add(title, 0, wx.ALIGN_LEFT|wx.ALL, padding)
self.sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, padding)
self.SetSizer(self.sizer)
def add_stuff(self, stuff):
'''Add aditional widgets to the bottom of the page'''
self.sizer.Add(stuff, 0, wx.EXPAND|wx.ALL, padding)
def SetNext(self, next):
'''Set the next page'''
self.next = next
def SetPrev(self, prev):
'''Set the previous page'''
self.prev = prev
def GetNext(self):
'''Return the next page'''
return self.next
def GetPrev(self):
'''Return the previous page'''
return self.prev
class wizard(wx.adv.Wizard):
'''Add pages to this wizard object to make it useful.'''
def __init__(self, title, img_filename=""):
# img could be replaced by a py string of bytes
if img_filename and os.path.exists(img_filename):
img = wx.Bitmap(img_filename)
else: img = wx.NullBitmap
wx.adv.Wizard.__init__(self, None, -1, title, img)
self.pages = []
# Lets catch the events
self.Bind(wx.adv.EVT_WIZARD_PAGE_CHANGED, self.on_page_changed)
self.Bind(wx.adv.EVT_WIZARD_PAGE_CHANGING, self.on_page_changing)
self.Bind(wx.adv.EVT_WIZARD_CANCEL, self.on_cancel)
self.Bind(wx.adv.EVT_WIZARD_FINISHED, self.on_finished)
def add_page(self, page):
'''Add a wizard page to the list.'''
if self.pages:
previous_page = self.pages[-1]
page.SetPrev(previous_page)
previous_page.SetNext(page)
self.pages.append(page)
def run(self):
self.RunWizard(self.pages[0])
def on_page_changed(self, evt):
'''Executed after the page has changed.'''
if evt.GetDirection(): dir = "forward"
else: dir = "backward"
page = evt.GetPage()
print ("page_changed: %s, %s\n" % (dir, page.__class__))
def on_page_changing(self, evt):
'''Executed before the page changes, so we might veto it.'''
if evt.GetDirection(): dir = "forward"
else: dir = "backward"
page = evt.GetPage()
print ("page_changing: %s, %s\n" % (dir, page.__class__))
def on_cancel(self, evt):
'''Cancel button has been pressed. Clean up and exit without continuing.'''
page = evt.GetPage()
print ("on_cancel: %s\n" % page.__class__)
# Prevent cancelling of the wizard.
if page is self.pages[0]:
wx.MessageBox("Cancelling on the first page has been prevented.", "Sorry")
evt.Veto()
def on_finished(self, evt):
'''Finish button has been pressed. Clean up and exit.'''
print ("OnWizFinished\n")
if __name__ == '__main__':
app = wx.App() # Start the application
# Create wizard and add any kind pages you'd like
mywiz = wizard('Simple Wizard', img_filename='wiz.png')
page1 = wizard_page(mywiz, 'Stage 1') # Create a first page
#page1.add_stuff(wx.StaticText(page1, -1, 'Hola'))
page1.add_stuff(wx.CheckBox(page1,-1,'Argument1',(35,40),(150,20)))
page1.add_stuff(wx.CheckBox(page1,-1,'Argument2',(35,60),(150,20)))
page1.add_stuff(wx.CheckBox(page1,-1,'Argument3',(35,80),(150,20)))
mywiz.add_page(page1)
# Add some more pages
mywiz.add_page( wizard_page(mywiz, 'Stage 2') )
mywiz.add_page( wizard_page(mywiz, 'Stage 3') )
mywiz.add_page( wizard_page(mywiz, 'Stage 4') )
mywiz.run() # Show the main window
# Cleanup
mywiz.Destroy()
#del app
app.MainLoop()
del app
when I am using the API of Object_detection,I followed the instruction ,everything is fine .However ,when I begin to test my picture , I met a problem , it seems that the function named
" visualize_boxes_and_labels_on_image_array " ( in the 57 line ) didn't work . Here is my source codes
import cv2
import numpy as np
import tensorflow as tf
from object_detection.utils import label_map_util
from object_detection.utils import visualization_utils as vis_util
class TOD(object):
def __init__(self):
self.PATH_TO_CKPT = '/home/xiyou/Desktop/ssd_training/result/frozen_inference_graph.pb'
self.PATH_TO_LABELS = '/home/xiyou/Desktop/ssd_training/detection_for_smoke.pbtxt'
self.NUM_CLASSES = 1
self.detection_graph = self._load_model()
self.category_index = self._load_label_map()
def _load_model(self):
detection_graph = tf.Graph()
with detection_graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(self.PATH_TO_CKPT, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def, name='')
return detection_graph
def _load_label_map(self):
label_map = label_map_util.load_labelmap(self.PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map,
max_num_classes=self.NUM_CLASSES,
use_display_name=True)
category_index = label_map_util.create_category_index(categories)
return category_index
def detect(self, image):
with self.detection_graph.as_default():
with tf.Session(graph=self.detection_graph) as sess:
# Expand dimensions since the model expects images to have shape: [1, None, None, 3]
image_np_expanded = np.expand_dims(image, axis=0)
image_tensor = self.detection_graph.get_tensor_by_name('image_tensor:0')
boxes = self.detection_graph.get_tensor_by_name('detection_boxes:0')
scores = self.detection_graph.get_tensor_by_name('detection_scores:0')
classes = self.detection_graph.get_tensor_by_name('detection_classes:0')
num_detections = self.detection_graph.get_tensor_by_name('num_detections:0')
# Actual detection.
(boxes, scores, classes, num_detections) = sess.run(
[boxes, scores, classes, num_detections],
feed_dict={image_tensor: image_np_expanded})
print(boxes, scores, classes, num_detections)
#print(np.squeeze(boxes))
# Visualization of the results of a detection.
#######Here is the problem
# image1 = vis_util.visualize_boxes_and_labels_on_image_array(
image, #######Here is the problem
np.squeeze(boxes),
np.squeeze(classes).astype(np.int32),
np.squeeze(scores),
self.category_index,
use_normalized_coordinates=True,
line_thickness=50,
)
#print(np.squeeze(boxes),np.squeeze(classes))
cv2.namedWindow("detection")
cv2.imshow("detection", image1)
cv2.waitKey(0)
if __name__ == '__main__':
image = cv2.imread('/home/xiyou/Pictures/timg1.jpg')
detecotr = TOD()
detecotr.detect(image)
when I run this code , the image did show ,but nothing changed , no detected area in the pic and no an other informations . the input pic is the same as the out image . But when I was Debug , I found the Varibles such as soucres , classes , boxes do have values.
Is anyone can help me ? Thanks!!!
And my Tensorflow version is 1.4.0 , CUDA 8.0 in Ubuntu 16.04
If I create my UI in QT Designer (and import UI to the script), how can I hide and show tabs in my script?
class Tool(QMainWindow, uiTool.Ui_Tool):
def __init__(self):
super(Tool, self).__init__()
# SETUP UI
self.setupUi(self)
# self.tabWidget.removeTab() ???
There is no way to hide/show the tabs in a tab-widget, so you will need to remove and replace them instead.
Below is a demo script that shows how to do this. I have not attempted to keep track of the original indexes in this example - it just shows the basic usage of the methods involved:
import sys
from PyQt5 import QtCore, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(354, 268)
self.gridLayout = QtWidgets.QGridLayout(Form)
self.gridLayout.setObjectName("gridLayout")
self.tabWidget = QtWidgets.QTabWidget(Form)
self.tabWidget.setObjectName("tabWidget")
self.tabRed = QtWidgets.QWidget()
self.tabRed.setObjectName("tabRed")
self.tabWidget.addTab(self.tabRed, "")
self.tabBlue = QtWidgets.QWidget()
self.tabBlue.setObjectName("tabBlue")
self.tabWidget.addTab(self.tabBlue, "")
self.tabGreen = QtWidgets.QWidget()
self.tabGreen.setObjectName("tabGreen")
self.tabWidget.addTab(self.tabGreen, "")
self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 2)
self.buttonRemove = QtWidgets.QPushButton(Form)
self.buttonRemove.setObjectName("buttonRemove")
self.gridLayout.addWidget(self.buttonRemove, 1, 0, 1, 1)
self.buttonRestore = QtWidgets.QPushButton(Form)
self.buttonRestore.setObjectName("buttonRestore")
self.gridLayout.addWidget(self.buttonRestore, 1, 1, 1, 1)
self.retranslateUi(Form)
self.tabWidget.setCurrentIndex(2)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabRed), _translate("Form", "Red"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabBlue), _translate("Form", "Blue"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabGreen), _translate("Form", "Green"))
self.buttonRemove.setText(_translate("Form", "Remove"))
self.buttonRestore.setText(_translate("Form", "Restore"))
class Window(QtWidgets.QWidget, Ui_Form):
def __init__(self):
super(Window, self).__init__()
self.setupUi(self)
self.buttonRemove.clicked.connect(self.handleButtonRemove)
self.buttonRestore.clicked.connect(self.handleButtonRestore)
self.tab_pages = []
for index in range(self.tabWidget.count()):
self.tab_pages.append((
self.tabWidget.widget(index),
self.tabWidget.tabText(index),
))
def handleButtonRemove(self):
index = self.tabWidget.currentIndex()
if index >= 0:
self.tabWidget.removeTab(index)
def handleButtonRestore(self):
for page, title in self.tab_pages:
if self.tabWidget.indexOf(page) < 0:
self.tabWidget.addTab(page, title)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 100, 300, 200)
window.show()
sys.exit(app.exec_())
It's been a while I'm searching all over the internet for that, but still couldn't get the answer... basically I have a QVBoxLayout which contains several frames - and each frame contains a button which function is to delete its parent frame. The main code was created using QT Designer and pyuic4. I wrote the two additional functions, one works perfectly ("createFrame") but I'm struggling with the "deleteFrame" one. the label inside the frame shows the index of that frame in the vert_layout "array". the problem I noted on my code is that, using it that way, I can only delete the last frame added. So, can someone help me with this issue?
please see my code below:
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
#Custom button that sends out its own instance as the signal
class MyPushButton(QtGui.QPushButton):
mySignal = QtCore.pyqtSignal(QtGui.QWidget)
def mousePressEvent(self, *args, **kwargs):
self.mySignal.emit(self)
class Functions:
def createFrame(self,mainWindow):
#just local frame no need to store it in the class
frame = QtGui.QFrame()
frame.setGeometry(QtCore.QRect(10, 10, 241, 61))
frame.setFrameShape(QtGui.QFrame.StyledPanel)
frame.setFrameShadow(QtGui.QFrame.Raised)
frame.setObjectName(_fromUtf8("frame"))
pushButton_2 = MyPushButton(frame)
pushButton_2.setGeometry(QtCore.QRect(94, 10, 141, 41))
pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
label = QtGui.QLabel(frame)
label.setGeometry(QtCore.QRect(20, 10, 71, 41))
label.setFrameShape(QtGui.QFrame.NoFrame)
label.setAlignment(QtCore.Qt.AlignCenter)
#the vert_layout belongs to class Ui_MainWindow
mainWindow.vert_layout.addWidget(frame)
label.setObjectName(_fromUtf8("label"))
label.setText(str(mainWindow.vert_layout.indexOf(frame)))
pushButton_2.setText(_translate("MainWindow", "delete this frame and all\n its childs", None))
pushButton_2.mySignal.connect(self.deleteFrame)
#my initial idea was to include the mainWindow (instance of
#Ui_MainWindow class in order to use vert_layout - but apparently
#I need to modify the signal as well, right?
def deleteFrame(self,ref,mainWindow):
#finding the index of the FRAME (mybutton's parent)
#that is to be deleted
frame = mainWindow.vert_layout.itemAt(self.vert_layout.indexOf(ref.parent()))
widget = frame.widget()
if widget is not None:
widget.deleteLater()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(400, 284)
self.vert_layout = QtGui.QVBoxLayout()
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.scrollArea = QtGui.QScrollArea(self.centralwidget)
self.scrollArea.setGeometry(QtCore.QRect(10, 10, 281, 261))
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollAreaWidgetContents = QtGui.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 277, 257))
self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents"))
self.scrollAreaWidgetContents.setLayout(self.vert_layout)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(310, 20, 75, 23))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
f = Functions()
self.pushButton.clicked.connect(lambda: f.createFrame())
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.pushButton.setText(_translate("MainWindow", "create", None))
class Main(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__== '__main__':
app = QtGui.QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
All you are currently doing is deleting the self.frame widget each time.
So only the last created one gets deleted. And not the one you actually click on.
Modified your code for what you need. Hope it helps you understand.
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
#Custom button that sends out its own instance as the signal
class MyPushButton(QtGui.QPushButton):
mySignal = QtCore.pyqtSignal(QtGui.QWidget)
def mousePressEvent(self, *args, **kwargs):
self.mySignal.emit(self)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(400, 284)
self.vert_layout = QtGui.QVBoxLayout()
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.scrollArea = QtGui.QScrollArea(self.centralwidget)
self.scrollArea.setGeometry(QtCore.QRect(10, 10, 281, 261))
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollAreaWidgetContents = QtGui.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 277, 257))
self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents"))
self.scrollAreaWidgetContents.setLayout(self.vert_layout)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(310, 20, 75, 23))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.pushButton.clicked.connect(lambda: self.createFrame())
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.pushButton.setText(_translate("MainWindow", "create", None))
def createFrame(self):
#just local frame no need to store it in the class
frame = QtGui.QFrame()
frame.setGeometry(QtCore.QRect(10, 10, 241, 61))
frame.setFrameShape(QtGui.QFrame.StyledPanel)
frame.setFrameShadow(QtGui.QFrame.Raised)
frame.setObjectName(_fromUtf8("frame"))
pushButton_2 = MyPushButton(frame)
pushButton_2.setGeometry(QtCore.QRect(94, 10, 141, 41))
pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
label = QtGui.QLabel(frame)
label.setGeometry(QtCore.QRect(20, 10, 71, 41))
label.setFrameShape(QtGui.QFrame.NoFrame)
label.setAlignment(QtCore.Qt.AlignCenter)
self.vert_layout.addWidget(frame)
label.setObjectName(_fromUtf8("label"))
label.setText(str(self.vert_layout.indexOf(frame)))
pushButton_2.setText(_translate("MainWindow", "delete this frame and all\n its childs", None))
pushButton_2.mySignal.connect(self.deleteFrame)
def deleteFrame(self,ref):
#finding the index of the FRAME (mybutton's parent)
#that is to be deleted
frame = self.vert_layout.itemAt(self.vert_layout.indexOf(ref.parent()))
widget = frame.widget()
if widget is not None:
widget.deleteLater()
class Main(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__== '__main__':
app = QtGui.QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
I am working with a QMainWindow and adding a QTableView widget. The table is to be filled with data from a csv file. The csv file first row has the headers, but I cannot find how to write that row into the headers. Even inputting a test header list does not work.
Also I want to reverse sort on the "time" column.
Here is code restricted to mostly the table:
import sys
import csv
from PyQt4 import QtGui
from PyQt4.QtCore import *
from array import *
class UserWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(UserWindow, self).__init__()
self.specModel = QtGui.QStandardItemModel(self)
self.specList = self.createSpecTable()
self.initUI()
def specData(self):
with open('testFile.csv', 'rb') as csvInput:
for row in csv.reader(csvInput):
if row > 0:
items = [QtGui.QStandardItem(field) for field in row]
self.specModel.appendRow(items)
def createSpecTable(self):
self.specTable = QtGui.QTableView()
# This is a test header - different from what is needed
specHdr = ['Test', 'Date', 'Time', 'Type']
self.specData()
specM = specTableModel(self.specModel, specHdr, self)
self.specTable.setModel(specM)
self.specTable.setShowGrid(False)
vHead = self.specTable.verticalHeader()
vHead.setVisible(False)
hHead = self.specTable.horizontalHeader()
hHead.setStretchLastSection(True)
self.specTable.sortByColumn(3, Qt.DescendingOrder)
return self.specTable
def initUI(self):
self.ctr_frame = QtGui.QWidget()
self.scnBtn = QtGui.QPushButton("Sample")
self.refBtn = QtGui.QPushButton("Reference")
self.stpBtn = QtGui.QPushButton("Blah")
# List Window
self.specList.setModel(self.specModel)
# Layout of Widgets
pGrid = QtGui.QGridLayout()
pGrid.setSpacing(5)
pGrid.addWidget(self.scnBtn, 3, 0, 1, 2)
pGrid.addWidget(self.refBtn, 3, 2, 1, 2)
pGrid.addWidget(self.stpBtn, 3, 4, 1, 2)
pGrid.addWidget(self.specList, 10, 0, 20, 6)
self.ctr_frame.setLayout(pGrid)
self.setCentralWidget(self.ctr_frame)
self.statusBar()
self.setGeometry(300, 300, 400, 300)
self.setWindowTitle('Test')
class specTableModel(QAbstractTableModel):
def __init__(self, datain, headerdata, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain
self.headerdata = headerdata
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.headerdata[col]
return None
def main():
app = QtGui.QApplication(sys.argv)
app.setStyle(QtGui.QStyleFactory.create("plastique"))
ex = UserWindow()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
and here is a really short csv file:
Run,Date,Time,Comment
data1,03/03/2014,00:04,Reference
data2,03/03/2014,02:00,Reference
data5,03/03/2014,02:08,Sample
data6,03/03/2014,13:57,Sample
Also the rowCount & columnCount definitions do not work.
Worked out answers to what I posted: Wrote a 'getHeader' function simply to read the first line of the csv file and returned the list. Added the following to the createSpecTable function:
specHdr = self.getHeader()
self.specModel.setHorizontalHeaderLabels(specHdr)
self.specModel.sort(2, Qt.DescendingOrder)
The last statement solved the reverse sort problem. The header line from the csv file was removed from the table by adding a last line to the specData function:
self.specModelremoveRow(0).
Finally the rowCount and columnCount were corrected with:
def rowCount(self, parent):
return self.arraydata.rowCount()
def columnCount(self, parent):
return self.arraydata.columnCount()