3 Replies - 4298 Views - Last Post: 22 July 2011 - 03:27 PM Rate Topic: -----

#1 duffman18  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 54
  • Joined: 20-October 10

PyQt help

Posted 27 October 2010 - 08:51 AM

First off I would like to that you all, this site has been a tremendous help in my process of learning Python. I am now trying to lean how to use PyQt4 to create GUIs. I have gone through a simple tutorial for the PyQt library that went over a few things that helped me get started in PyQt, but now I am having a problem sorting through all of the available widgets and deciding what widgets I need to use or if I have to make my own. What I am trying to do is have my main window split into 2 sections, the first section has a list of different objects, and each object is drag-able so that when you drag an object to the other section it puts an image or draws an image that can move around and interact with other objects that have been dragged over. Basically it will be like a layout editor for a bunch of preset shapes. What I am currently panning on using is the QTreeWidget for the list of objects and the QGraphicsView for the layout editing area. Will these widgets work for what I am trying to do?

Is This A Good Question/Topic? 0
  • +

Replies To: PyQt help

#2 duffman18  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 54
  • Joined: 20-October 10

Re: PyQt help

Posted 29 October 2010 - 12:10 PM

Ok so after lots of reading and playing around with pyQt and QGraphicsScenes I have decided that GraphicsScenes are probably the best way to achieve the functionality that I want my program to have. The problem I am having now is I can't get my functions to work properly with my QGraphicsView that I have on my window. I have built my main window in QtDesigner and Compiled the .ui file to make my .py file which reads as follows:
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'graphics.ui'
#
# Created: Fri Oct 29 14:08:22 2010
#      by: PyQt4 UI code generator 4.7.7
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        Mainwindow.setObjectName(_fromUtf8("MainWindow"))
        Mainwindow.resize(500, 230)
        Mainwindow.setMinimumSize(QtCore.QSize(300, 200))
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.view1 = QtGui.QGraphicsView(self.centralwidget)
        self.view1.setMouseTracking(False)
        self.view1.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.view1.setAcceptDrops(True)
        self.view1.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
        self.view1.setResizeAnchor(QtGui.QGraphicsView.NoAnchor)
        self.view1.setObjectName(_fromUtf8("view1"))
        self.horizontalLayout.addWidget(self.view1)
        self.text = QtGui.QLineEdit(self.centralwidget)
        self.text.setMaximumSize(QtCore.QSize(150, 16777215))
        self.text.setObjectName(_fromUtf8("text"))
        self.horizontalLayout.addWidget(self.text)
        Mainwindow.setCentralWidget(self.centralwidget)
        self.menuBar = QtGui.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 500, 21))
        self.menuBar.setObjectName(_fromUtf8("menuBar"))
        self.menuAdd = QtGui.QMenu(self.menuBar)
        self.menuAdd.setObjectName(_fromUtf8("menuAdd"))
        Mainwindow.setMenuBar(self.menuBar)
        self.actionRectangle = QtGui.QAction(MainWindow)
        self.actionRectangle.setObjectName(_fromUtf8("actionRectangle"))
        self.actionText = QtGui.QAction(MainWindow)
        self.actionText.setObjectName(_fromUtf8("actionText"))
        self.menuAdd.addAction(self.actionRectangle)
        self.menuAdd.addAction(self.actionText)
        self.menuBar.addAction(self.menuAdd.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        Mainwindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
        self.menuAdd.setTitle(QtGui.QApplication.translate("MainWindow", "Add", None, QtGui.QApplication.UnicodeUTF8))
        self.actionRectangle.setText(QtGui.QApplication.translate("MainWindow", "Rectangle", None, QtGui.QApplication.UnicodeUTF8))
        self.actionText.setText(QtGui.QApplication.translate("MainWindow", "Text", None, QtGui.QApplication.UnicodeUTF8))



So with this UI made I want to add functionality to the window but the functions I make aren't being used. I have tried many different ways of declaration, but haven't had any luck. I was trying to get it to when it first stats up to draw the words "Hello World" and a rectangle(which it does), and when you type text in the Text Entry box and drag it to the graphics view I want it to draw new text in the graphics view. Also when you click the Add>Text option from the menu bar, it writes "New Text" in the graphics view box. I think I can figure out the coding that goes inside the functions, I just can't figure out how to get my actions on the GUI to call the functions. Any help would be great. Thanks

# -*- coding: utf-8 -*-

"""The user interface for our app"""

import os,sys

# Import Qt modules
from PyQt4 import QtCore,QtGui,QtOpenGL

# Import the compiled UI module
from graphics import Ui_MainWindow

# Create a class for our main window
class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainwindow.__init__(self)

        # This is always the same
        self.ui=Ui_MainWindow()
        self.ui.setupUi(self)

        # Make a GraphicsScene
        self.scene=QtGui.QGraphicsScene()
        self.ui.view1.setScene(self.scene)
        self.ui.text.setDragEnabled(True)

        self.scene.setSceneRect(0,0,200,100)

        # Make it openGL accelerated
        self.ui.view1.setViewport(QtOpenGL.QGLWidget())

        self.populate()



    def populate(self):
        """
        Puts a few Items into the scene
        """
        font = QtGui.QFont('Times')
        font.setPointSize(20)
        
        self.Item1 = QtGui.QGraphicsTextItem("Hello World")
        self.Item1.setFont(font)
        self.Item1.setPos(60,20)
        self.scene.addItem(self.Item1)

        self.Item2 = QtGui.QGraphicsRectItem()
        self.Item2.setRect(5,12,15,30)
        self.scene.addItem(self.Item2)

    def on_view1_dragEnterEvent(self, event):
        event.accept()

    def on_actionText(self,checked = None):
        """
        Should add a new text item reading 'New Text' in the scene
        """
        if checked is None: return
        self.Item3 = Qt.Gui.QGraphicsTextItem('New Text')
        font = QtGui.QFont('Arial')
        self.Item3.setFont(font)
        self.Item3.setPos(1,1)
        self.scene.addItem(self.Item3)

    def on_text_dragLeaveEvent(self, event):
        event.accept()

    def on_view1_dropEvent(self, event):
        """
        Should add a new text item in scene
        """
        self.Item4 = Qt.Gui.QGraphicsTextItem(event.mimeData().text())
        self.Item4.setFont(QtGui.QFont('Times'))
        self.Item4.setPos(10,10)
        self.scene.addItem(self.Item4)

def main():
    # Again, this is boilerplate, it's going to be the same on
    # almost every app you write
    app = QtGui.QApplication(sys.argv)
    window=Main()
    window.show()
    # It's exec_ because exec is a reserved word in Python
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()


Was This Post Helpful? 0
  • +
  • -

#3 duffman18  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 54
  • Joined: 20-October 10

Re: PyQt help

Posted 02 November 2010 - 01:05 PM

Well after hours and hours of searching the internet I finally found a way to get this to work. I searched many sites and tutorials, but I couldn't find any that explained how to specify event handlers for specific widgets when you used the Qt Designer. You would normally just re-implement the specific event handler inside the class for the specific widget you wanted to use. This is a problem because Qt Designer makes only a single class for each window you design and compile, so that method is not possible unless you code your entire program, which for anything but very simple examples is not a fun task. So I finally stumbled across an example program that did what I was looking for, however I am yet to find anything that explains it fully. So here is what I did to counter this problem:
#include my generated UI file
from main import Ui_mainWindow

class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainwindow.__init__(self)

        # This is always the same
        self.ui=Ui_mainWindow()
        self.ui.setupUi(self)

        #Set up the Event handlers (This is the code I needed to add)
        self.ui.workArea.__class__.dragEnterEvent = self.on_workArea_dragEnterEvent
        self.ui.workArea.__class__.dropEvent = self.on_workArea_dropEvent



And then you define your functions in your Main class like this:

    def on_workArea_dragEnterEvent(self, event):
        pass

    def on_workArea_dropEvent(self, event):
        pass



So this needs to be done for each event that is not handled by the "highest parent" widget in each Qt Designer file.

I saw lots of people viewed this thread without any answers for my questions so maybe this will help anyone that was facing the same problem.

PS. I am using PyQt4, so it may not work on PyQt3. Maybe someone could clear that up?
Was This Post Helpful? 1
  • +
  • -

#4 rlfrost  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 1
  • Joined: 22-July 11

Re: PyQt help

Posted 22 July 2011 - 03:27 PM

View Postduffman18, on 02 November 2010 - 01:05 PM, said:

Well after hours and hours of searching the internet I finally found a way to get this to work. I searched many sites and tutorials, but I couldn't find any that explained how to specify event handlers for specific widgets when you used the Qt Designer. You would normally just re-implement the specific event handler inside the class for the specific widget you wanted to use. This is a problem because Qt Designer makes only a single class for each window you design and compile, so that method is not possible unless you code your entire program, which for anything but very simple examples is not a fun task. So I finally stumbled across an example program that did what I was looking for, however I am yet to find anything that explains it fully. So here is what I did to counter this problem:
#include my generated UI file
from main import Ui_mainWindow

class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainwindow.__init__(self)

        # This is always the same
        self.ui=Ui_mainWindow()
        self.ui.setupUi(self)

        #Set up the Event handlers (This is the code I needed to add)
        self.ui.workArea.__class__.dragEnterEvent = self.on_workArea_dragEnterEvent
        self.ui.workArea.__class__.dropEvent = self.on_workArea_dropEvent



And then you define your functions in your Main class like this:

    def on_workArea_dragEnterEvent(self, event):
        pass

    def on_workArea_dropEvent(self, event):
        pass



So this needs to be done for each event that is not handled by the "highest parent" widget in each Qt Designer file.

I saw lots of people viewed this thread without any answers for my questions so maybe this will help anyone that was facing the same problem.

PS. I am using PyQt4, so it may not work on PyQt3. Maybe someone could clear that up?


This is a very nice hint about events. Just one note... if you have grouped the widgets for which you are trying to capture events (horizontally or vertically with the layout manager in qdesigner) you just need to omit the __class__ from the example above.

For example:

self.ui.workArea.__class__.dragEnterEvent = self.on_workArea_dragEnterEvent

becomes

self.ui.workArea.dragEnterEvent = self.on_workArea_dragEnterEvent

If you don't do this the layout manager will use the latest definition for all widgets that are grouped together.

Thanks for such a very useful post.

RLFrost
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1