Working With Classes & Placing Frame inside The Window But Giving Error - user-interface

being a starter I am facing this difficulty.
TypeError: module() takes at most 2 arguments (3 given)
I want to work with classes and thus making frame in window, and unable tracing error .What does this error mean? please suggest me some easy tutorial site or youtube lecture on completely covering the topics with classes. One guess i made was to pack it again maybe inside the root(window). So I took chance to make it this way, butttt.
from tkinter import \*
from tkinter import ttk
class kk(Tk):
def __init__(self):
super().__init__()
self.geometry("600x200")
class MainFrame(ttk):
def __init__(self, container):
super().__init__(container)
self.l1=ttk.Label(self, text= "Bill No.", font=("digital 7",12,"bold", "italic"))
self.l1.pack(padx=5, pady=5)
self.e1var=StringVar()
self.e1=ttk.Entry(self, textvariable=self.e1var,width=30,border=4, font=("digital 7",12,"bold", "italic"))
self.e1.pack(padx=5, pady=5)
self.l1=ttk.Label(self, text= "DESCRIPTION", font=("digital 7",12,"bold", "italic"))
self.l1.pack(padx=5, pady=5)
self.e1var=StringVar()
self.e1=ttk.Entry(self, textvariable=self.e1var,width=30,border=4, font=("digital 7",12,"bold", "italic"))
self.e1.pack(padx=5, pady=5)
self.pack(padx=5, pady=5)
if __name__=="__main__":
window=kk()
frame1=MainFrame(window)
window.mainloop()

The problem is that MainFrame is trying to inherit from a module, which is why the error mentions module. The way you've written the code, it appears you intended to inherit from ttk.Frame.
class MainFrame(ttk.Frame):

Related

Play image sequence using Qt QMainWindow

I have an image sequence rendered out. which I want to payback in a simple QMainWindow or QDialog. This is what I have sofar. It loads the images into the qlabel, but I cant see the label being updated, its just show the last loaded image, and nothing in between.
Maybe someone knows something?
from PySide import QtCore, QtGui
import shiboken
import maya.OpenMayaUI as apiUI
import time
def getMayaWindow():
"""
Get the main Maya window as a QtGui.QMainWindow instance
#return: QtGui.QMainWindow instance of the top level Maya windows
"""
ptr = apiUI.MQtUtil.mainWindow()
if ptr is not None:
return shiboken.wrapInstance(long(ptr), QtGui.QWidget)
class Viewer(QtGui.QMainWindow):
def __init__(self, parent = getMayaWindow()):
super(Viewer, self).__init__(parent)
self.setGeometry(400, 600, 400, 300)
self.setUi()
def setUi(self):
self.label = QtGui.QLabel()
self.setCentralWidget(self.label)
def showUi(self):
self.show()
def loadImage(self, path):
self.label.clear()
image = QtGui.QImage(path)
pp = QtGui.QPixmap.fromImage(image)
self.label.setPixmap(pp.scaled(
self.label.size(),
QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation))
x = Viewer()
x.showUi()
for i in range(1, 11):
x.loadImage("C://anim%03d.png" % i)
time.sleep(0.5)
You change pixmaps in loop and sleep (stop) all GUI thread, that's why your GUI freeze.
http://www.tutorialspoint.com/python/time_sleep.htm
It is not correct. qLabel.repaint() it is bad solution because it still blocks GUI. Of course you can use processEvents but it is bad approach too.
You should use QTimer for this purpose, use timeout() signal, create slot and change pixmaps in this slot. In this case your GUI will not be blocked because QTimer works asynchronously and images will be successfuly changed.
Same code with loop and sleep can help you only when this code will execute in another thread (multi threading) but it is not necessary because there is special class QTimer.

Works with QGridLayout not with QVBoxLayout

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, os, time
class SetName(QWidget):
def __init__(self):
QWidget.__init__(self)
self.show()
toplayout = QVBoxLayout()
self.setWindowTitle('Personal Info')
self.form_layout = QFormLayout()
self.setLayout(self.form_layout)
self.line_edit_param = QLineEdit(self)
self.line_edit_param.setPlaceholderText("Write Here")
self.form_layout.addRow('Write Name', self.line_edit_param)
toplayout.addLayout(self.form_layout)
self.setFocus()
class LearnApp(QDialog):
def __init__(self):
super(QDialog, self).__init__()
self.setWindowTitle("LearnApp")
self.active = False
close_button = QPushButton("Close")
close_button.clicked.connect(self.close)
self.check_button = QPushButton("Check")
self.check_button.clicked.connect(self.set_data)
self.tr = QTextEdit()
self.tr.setReadOnly(True)
# layout
layout = QHBoxLayout()
#layout.addWidget(self.button3)
sub_layout = QVBoxLayout()
sub_layout.addWidget(self.check_button)
sub_layout.addWidget(close_button)
layout.addLayout(sub_layout)
layout.addWidget(self.tr)
self.setLayout(layout)
self.setFocus()
def set_data(self):
print "in set_data"
SetName()
app = QApplication(sys.argv)
dialog = LearnApp()
dialog.show()
app.exec_()
This is the code I'm trying. If edit it with toplayout = QGridLayout(), program works fine but with toplayout = QVBoxLayout(), it gives message QLayout::addChildLayout: layout "" already has a parentand just flashes the new window. What could be the problem? How should I tackle this? I wanna use QVBoxLayout instead of QGridLayout
Firstly, the new window disappears straight away because you don't store a reference to it. You need to store a reference to the instance in your LearnApp class, or parent it to another Qt object outside of set_data() if you want it to stick around.
The error message regarding the layouts is not occurring because of your choice of layouts, but because you are calling
self.setLayout(self.form_layout)
and then
toplayout.addLayout(self.form_layout)
The first call assigns the layout to the instance of SetName, but in doing so also makes the instance the parent of self.form_layout. The second call is trying to add the same layout to toplayout and set it as the parent, but Qt sees that self.form_layout already has a parent (i.e. is being used elsewhere). This is what the error message is trying to tell you.
I suspect that instead of self.setLayout(self.form_layout), you intended to write something like
self.setLayout(toplayout)

How to interrupt QThread from PyQt GUI?

I'm writting an application that encrypt an image. The main problem is that i want to add to my GUI option to interrupt (or even terminate) an encrypting thread (while it is working) just by clicking an gui button. Gui and algorithm work fine (ia also provide a gui's progressbar connection) but when the thread start to procced i can't click anything on gui (even the terminating button). Beside that button is properly connected becuse if there occured an error in thread and gui i still working i can click the button and it terminate the process.
I thought that gui froze because thread was defined in gui function so I've moved it out of gui to main program function.
I want to point out that i don't create therad subclass (as Maya Posch suggest http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/)
Here is the code of main function:
def main():
app = QApplication(sys.argv)
cryptoThread = QtCore.QThread()
prog = ProgramWindow()
worker = ic.imageCryptographer()
worker.moveToThread(cryptoThread)
prog.progressButton.clicked.connect(lambda: prog.interruptEncrypting(cryptoThread))
prog.startEncrypting.connect(cryptoThread.start)
worker.encryptSignal.connect(prog.progressbar.setValue)
worker.done.connect(lambda: prog.endEncrypting(cryptoThread, worker))
cryptoThread.started.connect(lambda: worker.compute(prog.shareFlag, prog.binMatrix))
sys.exit(app.exec_())
functions from class ProgramWindow:
def interruptEncrypting(self, thread):
thread.terminate()
thread.wait()
self.interrupt()
return
def endEncrypting(self, thread, worker):
self.keys = worker.keys
thread.quit()
self.progressbarWidget.setVisible(False)
self.saveOption.setEnabled(True)
self.cryptoWorkdeskOption.setEnabled(True)
self.openCryptoWorkdesk()
def interrupt(self):
self.progressbarWidget.setVisible(False)
if self.state==1:
self.buttonSwapWidget.setVisible(True)
elif self.state==2:
self.keyChooseWidget.setVisible(True)
Variables: shareFlag and binMatrix has no connection to thread communication (their are variables necceseray to compute worker methods. StartEncrypting is a signal emited from one of ProgramWindow function.
Thanks in advance for any advice where I made a mistake or what should I do.
Yep, just tried it and can confirm what I already indicated in my comment. Although you moved worker to cryptoThread (and therefore all its methods) the moment you connect cryptoThread.started.connect(lambda: worker.compute(prog.shareFlag, prog.binMatrix)) you create a new lambda object which is not running within cryptoThread but within the main thread. That's why it does not run besides your main application. You would have to connect cryptoThread.started.connect(worker.compute) and pass the arguments in some additional initializer / configure method.
I tested it with the following code:
import sys
import time
from PyQt4 import QtGui, QtCore
class Worker(QtCore.QObject):
def __init__(self, parent=None):
QtCore.QObject.__init__(self, parent)
self.t1 = QtCore.QThread()
self.moveToThread(self.t1)
self.t1.start()
def do_stuff(self):
while True:
print 'loop'
time.sleep(1)
class MainWindow(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.worker = Worker()
self.button = QtGui.QPushButton('start', self)
self.button.clicked.connect(self.worker.do_stuff) # connect directly with worker's method do_stuff
#self.button.clicked.connect(lambda: self.worker.do_stuff()) # connect with lambda object containing do_stuff
app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())

Pyside - Change entire GUI when button is pressed

I'm totally new to pyside and I'm having a problem with my little program (and pyside layouts in general).
What I have is an UI with some QlineEdits, comboboxes and a button. After I have filled out the Qlines and press the button I want to either to open a new window with a completely new layout or preferably clear out the open window and fill it with a new layout based on the input from the qlines. Perhaps this is super basic but I can't get it to work. The reason is that I can't grasp how I would be able to replace or add new stuff to my gui when it's already set and shown.
Let's say I have a script like this:
import sys
import os
from PySide import QtCore, QtGui
class BasicGui(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.projectNameLbl1 = QtGui.QLabel('Label1')
self.projectNameLbl2 = QtGui.QLabel('Label2')
self.nextBtn = QtGui.QPushButton("Next")
self.projectNameEdit = QtGui.QLineEdit(self)
self.projectNameEdit2 = QtGui.QLineEdit(self)
grid = QtGui.QGridLayout()
grid.setSpacing(10)
grid.addWidget(self.projectNameLbl1, 2, 0)
grid.addWidget(self.projectNameEdit, 2, 1)
grid.addWidget(self.projectNameLbl2, 3, 0)
grid.addWidget(self.projectNameEdit2, 3, 1)
grid.addWidget(self.nextBtn, 4, 1)
self.setLayout(grid)
self.setGeometry(300, 300, 350, 300)
self.setWindowTitle('projectCreator')
self.show()
self.nextBtn.clicked.connect(self.nextPressed)
def nextPressed(self):
self.msgBox = QtGui.QMessageBox()
self.msgBox.setText("When this button is pressed I want to generate a new layout")
self.msgBox.exec_()
def main():
app = QtGui.QApplication(sys.argv)
ex = BasicGui()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Say that I enter 10 in the line next to label1 and 2 in the other and press Next.Now I want to clear everything out and create 2 new columns with 10 qlines in each (or something like that).
Excuse me if I'm being either to vague or if I'm just repeating myself. I'm tired and irritated and English is not my first language.
I would deeply appreciate any help I could get or a push in the right direction.
Edit: If it's easier to accomplish this with some other widgetype with tabs or something that's fine. All i want to do is generate new widgets after i have recieved input from the user.
What you'll want to do is used a QStackedLayout[1].
Create a QWidget.
Create your layout.
Call setLayout() on the widget with your layout as the argument.
Push the new widget onto the QStackedLayout.
Use QStackedLayout's setCurrentIndex() or setCurrentWidget() functions to set the current layout.
I did something similar in a project of mine. See https://github.com/shanet/Cryptully/blob/master/cryptully/qt/qChatTab.py for a more complete example. Also see Pyside Changing Layouts for a similar problem.
[1] http://qt-project.org/doc/qt-4.8/qstackedlayout.html

How to get the details of an event in wxPython

I have a section of code which returns events generated by a slider.
I bind the event with self.Bind(wx.EVT_SCROLL,self.OnSlide).
The code which handles the event reads something like:
def OnSlide(self,event):
widget = event.GetEventObject()
This is great but an error gets thrown every time the code is executed. It reads:
AttributeError: 'PyEventBinder' object has no attribute 'GetEventObject'
I want to be able to see which of the sliders generated the event but the error appears every time I attempt to find out.
How can I get the code to execute correctly?
Many thanks in advance.
To debug something like this, put the following as the first statement in your event handler:
import pdb; pdb.set_trace()
This will stop the execution of the program at this point and give you an interactive prompt. You can then issue the following command to find out what methods are available:
print dir(event)
When I was first learning wxPython I found this technique invaluable.
The following works for me on Windows 7, wxPython 2.8.10.1, Python 2.5
import wx
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="Tutorial")
# Add a panel so it looks the correct on all platforms
panel = wx.Panel(self, wx.ID_ANY)
slider = wx.Slider(panel, size=wx.DefaultSize)
slider.Bind(wx.EVT_SLIDER, self.onSlide)
#----------------------------------------------------------------------
def onSlide(self, event):
""""""
obj = event.GetEventObject()
print obj
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm().Show()
app.MainLoop()

Resources