简体   繁体   中英

PyQT - Positioning and Displaying a Custom Widget

I am attempting to use PyQT to position and display a custom widget. Thus far, I have a widget, and my window. I have been successful in displaying the widget through a layout, however, I am interested in using .move(x,y,) to position my widget before show()'ing it. Thus far my code is as follows:

import sys, random
from PyQt4 import QtGui, QtCore

# Robot Widget
class RobotLink(QtGui.QWidget):
    def __init__(self, parent, x, y, width, height, fill):
        super(RobotLink, self).__init__(parent)
        self._x        = x
        self._y        = y
        self._width    = width
        self._height   = height
        self._fill     = fill
        self._rotation = 0

    def paintEvent(self, e):
        painter = QtGui.QPainter()
        painter.begin(self)
        self.drawLink(painter)
        painter.end()

    def drawLink(self, painter):
        painter.setPen(QtGui.QColor(0, 0, 0))
        painter.setBrush(self._fill)
        painter.drawEllipse(self._x, self._y, self._width, self._height)

# Window
class Window(QtGui.QWidget):
    # Default Constructor, sets up the window GUI
    def __init__(self):
        super(Window, self).__init__()
        self.initUI()

    def initUI(self):
        self._link1 = RobotLink(self, 225, 400, 30, 150, QtCore.Qt.DiagCrossPattern)
        self._link2 = RobotLink(self, 0, 320, 30, 100, QtCore.Qt.Dense5Pattern)
        self._link3 = RobotLink(self, 225, 260, 30, 75, QtCore.Qt.Dense2Pattern)

        self._link1.move(0, 0)
        self._link1.show()

        self.setGeometry(300, 300, 800, 600)
        self.setWindowTitle("CSCE 452 - PaintBot")


    def paintEvent(self, e):
        super(Window, self).paintEvent(e)
        painter = QtGui.QPainter()
        painter.begin(self)
        self.drawBoundingBoxes(painter)
        painter.end()

    # Draws the boxes that define the robots workspace and
    # the control panel
    def drawBoundingBoxes(self, painter):
        color = QtGui.QColor(0, 0, 0)
        color.setNamedColor("#cccccc")
        painter.setPen(color)

        # Draw the robot workspace
        painter.setBrush(QtGui.QColor(255, 255, 255))
        painter.drawRect(10, 10, 500, 578)

        # Draw the control panel workspace
        painter.setBrush(QtGui.QColor(150, 150, 150))
        painter.drawRect(520, 10, 270, 578)

        # Draws the slider 'base'
        painter.setPen(QtGui.QColor(0, 0, 0))
        painter.drawLine(100, 570, 400, 570)

    def changeValue(self, value):
        self.wid.emit(QtCore.SIGNAL("updateRobot(int)"), value)
        self.wid.repaint()

# Setup the Window, and the Robot
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
app.exec_()

Any idea how to attach my widget, without a layout, position it and have it show inside of my window?

Couple of things I noticed in your code:

  1. you don't really need to define store x, y, width and height for your custom widget. Just call setGeometry with coordinates passed into the constructor. Widget already providers getGeometry, getHeight, getWidth, etc. methods which you can use to manipulate and paint your component.

  2. when you call drawEllipse in the child widget drawLink method, you're passing x and y coordinates into the function as rectangle beginning. From my understanding you should put there 0, 0 as those coordinates should be widget relative not the window relative.

I've made some changes to your code, see if it works for you

import sys, random
from PyQt4 import QtGui, QtCore

# Robot Widget
class RobotLink(QtGui.QWidget):
    def __init__(self, parent, x, y, width, height, fill):
        super(RobotLink, self).__init__(parent)
        self._fill     = fill
        self._rotation = 0
        self.setGeometry(x, y, width, height)

    def paintEvent(self, e):
        painter = QtGui.QPainter()
        painter.begin(self)
        self.drawLink(painter)
        painter.end()

    def drawLink(self, painter):
        painter.setPen(QtGui.QColor(0, 0, 0))
        painter.setBrush(self._fill)
        painter.drawEllipse(0, 0, self.width(), self.height())

# Window
class Window(QtGui.QWidget):
    # Default Constructor, sets up the window GUI
    def __init__(self):
        super(Window, self).__init__()
        self.initUI()

    def initUI(self):
        self._link1 = RobotLink(self, 10, 10, 100, 50, QtCore.Qt.DiagCrossPattern)
        self._link2 = RobotLink(self, 100, 100, 50, 100, QtCore.Qt.Dense5Pattern)
        self._link3 = RobotLink(self, 150, 150, 50, 50, QtCore.Qt.Dense2Pattern)

        self.setGeometry(300, 300, 800, 600)
        self.setWindowTitle("CSCE 452 - PaintBot")

    def paintEvent(self, e):
        super(Window, self).paintEvent(e)
        painter = QtGui.QPainter()
        painter.begin(self)
        self.drawBoundingBoxes(painter)
        painter.end()

    # Draws the boxes that define the robots workspace and
    # the control panel
    def drawBoundingBoxes(self, painter):
        color = QtGui.QColor(0, 0, 0)
        color.setNamedColor("#cccccc")
        painter.setPen(color)

        # Draw the robot workspace
        painter.setBrush(QtGui.QColor(255, 255, 255))
        painter.drawRect(10, 10, 500, 578)

        # Draw the control panel workspace
        painter.setBrush(QtGui.QColor(150, 150, 150))
        painter.drawRect(520, 10, 270, 578)

        # Draws the slider 'base'
        painter.setPen(QtGui.QColor(0, 0, 0))
        painter.drawLine(100, 570, 400, 570)

    def changeValue(self, value):
        self.wid.emit(QtCore.SIGNAL("updateRobot(int)"), value)
        self.wid.repaint()

# Setup the Window, and the Robot
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
app.exec_()

hope this helps, regards

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM