Posts: 2
Threads: 1
Joined: Mar 2020
Mar-25-2020, 01:30 PM
(This post was last modified: Mar-25-2020, 02:04 PM by Basti.)
Hi!
I'm new here and I'm hoping that you can help me a little bit here.
I work with Python 3.7, pyqt 5.13.2 and windows 8, if that is important.
I also did some reading about toolbars, but that didn't really help me with my problem so far.
My problem is that I want to create a box via toolbar click, which appears in my graphical scene with a button click. Creating the toolbar wasn't that difficult now, but I don't know how to write the function that creates the box.
At the moment I have three boxes loaded at the start of the program, but later I want to go over to the fact that they can only be added via the toolbar click. To simplify things, they should be created in the middle of the scene so Position(0,0).
However, i think i am barking up the wrong tree and sadly I can't get a proper function  .
Since Iam a beginner please have mercy  .
Here is my code I use... it is actually much bigger, but I cut it down to make it not so confusing, but even now its quiet long.
The funktion i am looking for is def addnewBox in editor_window.py in line 41, I just put a "?" because i dont how to do it at all:(
The Picture addBox.png for the toolbar in editor_window line 36 is from the website material.io with the name note_add.
From here: https://material.io/resources/icons/?ico...e=baseline
stay healthy in these times
editor_main.py
import sys
from PyQt5.QtWidgets import *
from editor_window import Window
if __name__ == '__main__':
app = QApplication(sys.argv)
wnd = Window()
wnd.editor.addBoxes()
wnd.show()
sys.exit(app.exec_())
editor_window.py
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from tests.testtoolbar.editor_main_widget import MainWidget
from tests.testtoolbar.editor_scene import Scene
from tests.testtoolbar.editor_box import Box
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.scene = Scene()
self.createToolBars()
# create node editor widget
self.editor = MainWidget(self)
self.setCentralWidget(self.editor)
# set window properties
self.setGeometry(200, 200, 800, 600)
self.setWindowTitle("Editor")
self.show()
def createToolBars(self):
# initialize toolbar
toolbar = QToolBar("my main toolbar")
toolbar.setIconSize(QSize(32, 32))
self.addToolBar(toolbar)
"buttons"
button_action = QAction(QIcon("addBox.png"), "New box 1", self)
button_action.setStatusTip("Add a new Box")
button_action.triggered.connect(self.addnewBox())
toolbar.addAction(button_action)
def addnewBox(self):
?
editor_scene.py
from tests.testtoolbar.editor_graphics_scene import GraphicsScene
class Scene():
def __init__(self):
super().__init__()
self.boxes = []
self.scene_width = 64000
self.scene_height = 64000
self.initUI()
def initUI(self):
self.grScene = GraphicsScene(self)
self.grScene.setGrScene(self.scene_width, self.scene_height)
def addBox(self, box):
self.boxes.append(box)
editor_graphics_scene.py
import math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class GraphicsScene(QGraphicsScene):
def __init__(self, scene, parent=None):
super().__init__(parent)
"Set the Setting for the Scene"
self.scene = scene
# settings
self.gridSize = 20
self.gridSquares = 5
self._color_background = QColor("#393939")
self._color_light = QColor("#2f2f2f")
self._color_dark = QColor("#292929")
self._pen_light = QPen(self._color_light)
self._pen_light.setWidth(1)
self._pen_dark = QPen(self._color_dark)
self._pen_dark.setWidth(2)
self.setBackgroundBrush(self._color_background)
def setGrScene(self, width, height):
self.setSceneRect(-width // 2, -height // 2, width, height)
"Draw the Lines in the Scene"
def drawBackground(self, painter, rect):
super().drawBackground(painter, rect)
# here we create our grid
left = int(math.floor(rect.left()))
right = int(math.ceil(rect.right()))
top = int(math.floor(rect.top()))
bottom = int(math.ceil(rect.bottom()))
first_left = left - (left % self.gridSize)
first_top = top - (top % self.gridSize)
# compute all lines to be drawn
lines_light, lines_dark = [], []
for x in range(first_left, right, self.gridSize):
if (x % (self.gridSize*self.gridSquares) != 0): lines_light.append(QLine(x, top, x, bottom))
else: lines_dark.append(QLine(x, top, x, bottom))
for y in range(first_top, bottom, self.gridSize):
if (y % (self.gridSize*self.gridSquares) != 0): lines_light.append(QLine(left, y, right, y))
else: lines_dark.append(QLine(left, y, right, y))
# draw the lines
painter.setPen(self._pen_light)
painter.drawLines(*lines_light)
painter.setPen(self._pen_dark)
painter.drawLines(*lines_dark)
editor_box.py
from editor_graphics_box import GraphicsBox
from editor_content_widget import ContentWidget
class Box():
def __init__(self, scene, title="Undefined Box"):
super().__init__()
self._title = title
self.scene = scene
self.content = ContentWidget(self)
self.grBox = GraphicsBox(self)
self.title = title
self.scene.addBox(self)
self.scene.grScene.addItem(self.grBox)
@property
def pos(self):
return self.grBox.pos()
def setPos(self, x, y):
self.grBox.setPos(x, y)
@property
def title(self):
return self._title
@title.setter
def title(self, value):
self._title = value
self.grBox.title = self._title
editor_graphics_box.py
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class GraphicsBox(QGraphicsItem):
def __init__(self, box, parent=None):
super().__init__(parent)
self.box = box
self.content = self.box.content
self._title_color = Qt.white
self._title_font = QFont("Ubuntu", 10)
self.width = 180
self.height = 180
self.edge_size = 10.0
self.title_horizontal_padding = 2.0
self.title_height = 24.0
self._padding = 4.0
self._pen_default = QPen(QColor("#7F000000"))
self._pen_selected = QPen(QColor("#FFFFA637"))
self._brush_title = QBrush(QColor("#FF313131"))
self._brush_background = QBrush(QColor("#E3212121"))
# init title
self.initTitle()
self.title = self.box.title
# init content
self.initContent()
self.initUI()
@property
def title(self): return self._title
@title.setter
def title(self, value):
self._title = value
self.title_item.setPlainText(self._title)
text_width = self.title_item.boundingRect().width() # set the width of the title
offset = self.width // 2 - text_width // 2 # double // to get a number without comma number
self.title_item.setPos( offset - self.title_horizontal_padding // 2, 0)
def boundingRect(self):
return QRectF(
0,
0,
self.width,
self.height
).normalized()
def initUI(self):
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemIsMovable)
def initTitle(self):
self.title_item = QGraphicsTextItem(self)
self.title_item.box = self.box
self.title_item.setDefaultTextColor(self._title_color)
self.title_item.setFont(self._title_font)
self.title_item.setPos(self._padding, 0) # (x,y)
def initContent(self):
self.grContent = QGraphicsProxyWidget(self)
self.content.setGeometry(self.edge_size, self.title_height + self.edge_size,
self.width - 2 * self.edge_size, self.height - 2 * self.edge_size - self.title_height)
self.grContent.setWidget(self.content)
def paint(self, painter, QStyleOptionGraphicsItem, widget=None):
# title
path_title = QPainterPath()
path_title.setFillRule(Qt.WindingFill)
path_title.addRoundedRect(0,0, self.width, self.title_height, self.edge_size, self.edge_size)
path_title.addRect(0, self.title_height - self.edge_size, self.edge_size, self.edge_size)
path_title.addRect(self.width - self.edge_size, self.title_height - self.edge_size, self.edge_size, self.edge_size)
painter.setPen(Qt.NoPen)
painter.setBrush(self._brush_title)
painter.drawPath(path_title.simplified())
# content
path_content = QPainterPath()
path_content.setFillRule(Qt.WindingFill)
path_content.addRoundedRect(0, self.title_height, self.width, self.height - self.title_height, self.edge_size, self.edge_size)
path_content.addRect(0, self.title_height, self.edge_size, self.edge_size)
path_content.addRect(self.width - self.edge_size, self.title_height, self.edge_size, self.edge_size)
painter.setPen(Qt.NoPen)
painter.setBrush(self._brush_background)
painter.drawPath(path_content.simplified())
# outline
path_outline = QPainterPath()
path_outline.addRoundedRect(0, 0, self.width, self.height, self.edge_size, self.edge_size)
painter.setPen(self._pen_default if not self.isSelected() else self._pen_selected)
painter.setBrush(Qt.NoBrush)
painter.drawPath(path_outline.simplified())
editor_graphics_view.py
from PyQt5.QtWidgets import QGraphicsView
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class GraphicsView(QGraphicsView):
def __init__(self, grScene, parent=None):
super().__init__(parent)
self.grScene = grScene
self.initUI()
self.setScene(self.grScene)
def initUI(self):
"make everthing looks smoother and more pixel"
self.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)
"Update the Scene in case of movement and reset the lines behind the object that was moved"
self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
"hide the scrollbars"
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
def mousePressEvent(self, event):
if event.button() == Qt.MiddleButton:
self.middleMouseButtonPress(event)
elif event.button() == Qt.LeftButton:
self.leftMouseButtonPress(event)
elif event.button() == Qt.RightButton:
self.rightMouseButtonPress(event)
else:
super().mousePressEvent(event)
def mouseReleaseEvent(self, event):
if event.button() == Qt.MiddleButton:
self.middleMouseButtonRelease(event)
elif event.button() == Qt.LeftButton:
self.leftMouseButtonRelease(event)
elif event.button() == Qt.RightButton:
self.rightMouseButtonRelease(event)
else:
super().mouseReleaseEvent(event)
"MIDDLE MOUSE BUTTON EVENT"
def middleMouseButtonPress(self, event):
super().mousePressEvent(event)
def middleMouseButtonRelease(self, event):
super().mousePressEvent(event)
"LEFT MOUSE BUTTON EVENT"
def leftMouseButtonPress(self, event):
super().mousePressEvent(event)
def leftMouseButtonRelease(self, event):
super().mouseReleaseEvent(event)
"RIGHT MOUSE BUTTON EVENT"
def rightMouseButtonPress(self, event):
super().mousePressEvent(event)
def rightMouseButtonRelease(self, event):
super().mouseReleaseEvent(event)
editor_content_widget.py
from PyQt5.QtWidgets import *
class ContentWidget(QWidget):
def __init__(self, box, parent=None):
self.box = box
super().__init__(parent)
self.initUI()
def initUI(self):
self.layout = QVBoxLayout()
self.layout.setContentsMargins(0,0,0,0)
self.setLayout(self.layout)
self.wdg_label = QLabel("Some Title")
self.layout.addWidget(self.wdg_label)
self.layout.addWidget(QTextEdit("foo"))
editor_main_widget.py
from PyQt5.QtWidgets import *
from editor_scene import Scene
from editor_box import Box
from editor_graphics_view import GraphicsView
class MainWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.initUI()
def initUI(self):
self.layout = QVBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.layout)
# crate graphics scene
self.scene = Scene()
# create graphics view
self.view = GraphicsView(self.scene.grScene, self)
self.layout.addWidget(self.view)
def addBoxes(self):
box1 = Box(self.scene, "Box 1")
box2 = Box(self.scene, "Box 2")
box3 = Box(self.scene, "Box 3")
box1.setPos(-350, -250)
box2.setPos(-75, 0)
box3.setPos(200, -150)
Actualy I found a mistake in the imports
in editor_scene.py it is
from editor_graphics_scene import GraphicsScene
in editor_window.py it is
from editor_main_widget import MainWidget
from editor_scene import Scene
from editor_box import Box
sorry for that
Posts: 6,800
Threads: 20
Joined: Feb 2020
Mar-25-2020, 04:03 PM
(This post was last modified: Mar-25-2020, 04:03 PM by deanhystad.)
If you put print("addnewbox called") inside the addnewbox method do you see anything when you press the toolbar button?
Posts: 2
Threads: 1
Joined: Mar 2020
Mar-26-2020, 11:41 AM
(This post was last modified: Mar-26-2020, 12:25 PM by Basti.)
When i make it like this:
def createToolBars(self):
# initialize toolbar
toolbar = QToolBar("my main toolbar")
toolbar.setIconSize(QSize(32, 32))
self.addToolBar(toolbar)
"buttons"
button_action = QAction(QIcon("addBox.png"), "New box 1", self)
button_action.setStatusTip("Add a new Box")
button_action.triggered.connect(self.addnewBox())
toolbar.addAction(button_action)
def addnewBox(self):
print("addnewbox called") I get an error:
Error: File "C:\Users\Sebastian\PycharmProjects\TUProject\tests\testtoolbar\editor_window.py", line 38, in createToolBars
button_action.triggered.connect(self.addnewBox())
TypeError: argument 1 has unexpected type 'NoneType'
I forgot to delete the bracket () behind the self.addnew Box:
button_action.triggered.connect(self.addnewBox) And now i get my output when i press the button Output: addnewbox called
so this works:)
currently the editor looks like this:
https://www.flickr.com/photos/[email protected]/
I uploaded a screenshot on flickr.com:)
|