Seite 1 von 5
Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 2. Dezember 2018, 17:14
von Atalanttore
Hallo
Heute wollte ich mit Qt geometrische Formen zeichnen. Folgender Code zum Zeichnen eines Rechtecks funktioniert noch.
Rechteck.py:
Code: Alles auswählen
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QBrush, QPen
from PyQt5 import QtCore
class MainWindow(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self)
self.pen = QPen(QtCore.Qt.red) # Außenliniefarbe
self.pen.setWidth(5) # Außenliniendicke
self.brush = QBrush(QtCore.Qt.blue) # Füllfarbe
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(self.pen)
painter.setBrush(self.brush)
painter.drawRect(50, 50, 200, 200)
def main():
app = QApplication(sys.argv)
main_window = MainWindow(app)
main_window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Im nächsten Schwierigkeitsgrad wollte ich dann Punktobjekte, die auf einer Kreisbahn angeordnet sind, mittels einer for-Schleife erstellen und zeichnen. Punktobjekte werden laut `print(points)` mit dem folgenden Code zwar erstellt, aber es erscheinen keine Punkte im `MainWindow`.
Punkte.py
Code: Alles auswählen
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QBrush
from PyQt5 import QtCore
import math
import sys
points = []
circle_points = 30
point_color = QtCore.Qt.red
point_diameter = 20
circle_diameter = 500
class MainWindow(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self)
self.setGeometry(0,0,800,800)
for i in range(circle_points):
angle = (360 / circle_points * i)
point = Point(self, angle, point_color, point_diameter, circle_diameter)
points.append(point)
print(points)
class Point(QWidget):
def __init__(self, main_window, angle, point_color, point_diameter, circle_diameter):
super().__init__()
self.main_window = main_window
self.x_center = self.width() / 2
self.y_center = self.height() / 2
self.point_color = point_color
self.point_diameter = point_diameter
self.circle_diameter = circle_diameter
self.angle = angle
self.brush = QBrush(self.point_color)
def paintEvent(self, event):
painter = QPainter(self.main_window)
painter.setBrush(self.brush)
x = self.x_center + (self.circle_diameter / 2 * math.cos(math.radians(self.angle)))
y = self.y_center + (self.circle_diameter / 2 * math.sin(math.radians(self.angle)))
x1 = int(x - self.point_diameter)
y1 = int(y - self.point_diameter)
x2 = int(x + self.point_diameter)
y2 = int(y + self.point_diameter)
print("Test")
painter.drawEllipse(x1, y1, x2, y2)
def main():
app = QApplication(sys.argv)
main_window = MainWindow(app)
main_window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
- Die Anweisung `print("Test")` wird gar nicht ausgeführt. Wo liegt der oder die Fehler?
- Warum braucht man zum Zeichnen eigentlich die Methode `paintEvent(self, event)`? Von den über Google gefundenen Erklärungen habe ich nur verstanden, dass damit wohl die Methode `paintEvent` der Klasse `QWidget` überschrieben wird.
Gruß
Atalanttore
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 2. Dezember 2018, 17:20
von __deets__
Da ist vieles im argen.
- Du benutzt widgets. Die wollen ziemlich sicher ueber ihre parent-Eigenschaft miteinander verbunden werden. Du uebergibst aber kein parent. Das widget haengt also "im leeren". Und das, obwohl du schon main_window mit reinreichst. Und darum wird wohl auch dein print nicht aufgerufen
- widgets sind nicht gedacht fuer so etwas. Die sind per Definition immer rechteckig, und eine Art Spielfeld oder Grafik daraus aufzubauen ist ungewoehnlich bis unmoeglich. Wenn du viele graphische Objekte darstellen willst, schau dir den QGraphicsView an, der ist dazu gedacht.
- das das mainwindow sich seine geometry selbst setzt macht es als allgemeines Objekt unnutzbar. Das sollte eigentlich gar nicht, bestenfalls von aussen, geschehen.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 2. Dezember 2018, 21:28
von Atalanttore
@__deets__: Soweit ich deine Vorschläge verstanden habe und mithilfe des Codebeispiels
hier habe ich den Code jetzt umgebaut (siehe unten). Leider werden auch mit dem umgebauten Code noch keine Punkte gezeichnet. Als Fehlermeldung erscheint nun `QPainter::setBrush: Painter not active` in der Konsole.
__deets__ hat geschrieben: ↑Sonntag 2. Dezember 2018, 17:20
- Du benutzt widgets. Die wollen ziemlich sicher ueber ihre parent-Eigenschaft miteinander verbunden werden. Du uebergibst aber kein parent. Das widget haengt also "im leeren". Und das, obwohl du schon main_window mit reinreichst. Und darum wird wohl auch dein print nicht aufgerufen
Ein `parent` wird jetzt übergeben und `print("Test")` wird aufgerufen.
__deets__ hat geschrieben: ↑Sonntag 2. Dezember 2018, 17:20 - widgets sind nicht gedacht fuer so etwas. Die sind per Definition immer rechteckig, und eine Art Spielfeld oder Grafik daraus aufzubauen ist ungewoehnlich bis unmoeglich. Wenn du viele graphische Objekte darstellen willst, schau dir den QGraphicsView an, der ist dazu gedacht.
- das das mainwindow sich seine geometry selbst setzt macht es als allgemeines Objekt unnutzbar. Das sollte eigentlich gar nicht, bestenfalls von aussen, geschehen.
`MainWindow()` wurde zu `GraphicsWindow()` und erbt von `QGraphicsView`. Hat sich damit auch das Problem mit der `geometry` gelöst?
Der umgebaute Code:
Code: Alles auswählen
from PyQt5.QtCore import QRectF
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
from PyQt5.QtGui import QPainter, QBrush
import math
points = []
circle_points = 30
point_color = QtCore.Qt.red
point_diameter = 20
circle_diameter = 500
class Point(QGraphicsItem):
def __init__(self, angle, point_color, point_diameter, circle_diameter, x_center, y_center):
super(Point, self).__init__()
self.x_center = x_center
self.y_center = y_center
self.point_color = point_color
self.point_diameter = point_diameter
self.circle_diameter = circle_diameter
self.angle = angle
self.brush = QBrush(self.point_color)
def paint(self, painter, option, widget):
painter = QPainter()
painter.setBrush(self.brush)
x = self.x_center + (self.circle_diameter / 2 * math.cos(math.radians(self.angle)))
y = self.y_center + (self.circle_diameter / 2 * math.sin(math.radians(self.angle)))
x1 = int(x - self.point_diameter)
y1 = int(y - self.point_diameter)
x2 = int(x + self.point_diameter)
y2 = int(y + self.point_diameter)
print("Test")
painter.drawEllipse(x1, y1, x2, y2)
def boundingRect(self):
return QRectF(0,0,800,800)
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent)
scene = QGraphicsScene(self)
self.x_center = self.width() / 2
self.y_center = self.height() / 2
for i in range(circle_points):
angle = (360 / circle_points * i)
point = Point(angle, point_color, point_diameter, circle_diameter, self.x_center, self.y_center)
points.append(point)
scene.addItem(point)
scene.setSceneRect(0, 0, 800, 800)
self.setScene(scene)
self.setCacheMode(QGraphicsView.CacheBackground)
def main():
import sys
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Bei der Methode `paint()` in der Klasse `Point(QGraphicsItem)` bemäkelt meine IDE (PyCharm) folgendes:
Code: Alles auswählen
Signature of method 'Point.paint()' does not match signature of base method in class 'QGraphicsItem'
This inspection detects inconsistencies in overriding method signatures.
In der
Doku zu `paint()` werden aber genauso `painter`, `option` und `widget` als formale Parameter genannt. Was ist hier mit Signatur gemeint?
Gruß
Atalanttore
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 2. Dezember 2018, 21:48
von __deets__
Ich würde erstmal mit den eingebauten Items spielen, bevor ich ein eigenes erstellen würde. Ggf reichen die schon völlig aus.
Das geometry Ding hat ja was mit der Position und Dimension des Fensters selbst zu tun. Das Scene rect legt hingegen die Koordinaten der dargestellten Items fest - das wird dann umtransformiert. Das ist ja was komplett anderes.
Mein Punkt richtet sich gegen ersteres: entweder man bietet einen fullscreen Modus an, den der User wieder verlassen kann. Oder der User positioniert das Fenster selbst. Das vorzugeben ist ein usability-no-no. Du könntest die letzte Position dir merken und restaurieren. Das wäre ok.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 2. Dezember 2018, 22:18
von __deets__
Achso: warum pycharm da bockig ist - kA. Ich benutze das nicht, aber generell ist Typinferenz in Python schwierig. Das kann schon mal sein, dass das nicht klappt. Wenn der Code tut, kann es so falsch nicht sein.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Montag 3. Dezember 2018, 22:53
von Atalanttore
Ich habe jetzt `QGraphicsItem` durch `QGraphicsEllipseItem` (
QGraphicsEllipseItem → QAbstractGraphicsShapeItem → QGraphicsItem) ersetzt. Die Methode `setRect()` habe ich dann auch mal benutzt. Leider wird nach wie vor nichts gezeichnet und es erscheint immer noch folgende Fehlermeldung in Konsole:
Code:
Code: Alles auswählen
from PyQt5.QtCore import QRectF
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsEllipseItem
from PyQt5.QtGui import QPainter, QBrush
import math
points = []
circle_points = 30
point_color = QtCore.Qt.red
point_diameter = 20
circle_diameter = 500
class Point(QGraphicsEllipseItem):
def __init__(self, angle, point_color, point_diameter, circle_diameter, x_center, y_center):
super(Point, self).__init__()
self.x_center = x_center
self.y_center = y_center
self.point_color = point_color
self.point_diameter = point_diameter
self.circle_diameter = circle_diameter
self.angle = angle
self.brush = QBrush(self.point_color)
def paint(self, painter, option, widget):
painter = QPainter()
painter.setBrush(self.brush)
x = self.x_center + (self.circle_diameter / 2 * math.cos(math.radians(self.angle)))
y = self.y_center + (self.circle_diameter / 2 * math.sin(math.radians(self.angle)))
x1 = int(x - self.point_diameter)
y1 = int(y - self.point_diameter)
x2 = int(x + self.point_diameter)
y2 = int(y + self.point_diameter)
self.setRect(x1, y1, x2, y2)
painter.drawEllipse(x1, y1, x2, y2)
print("Ich werde auch ausgeführt :-)")
def boundingRect(self):
return QRectF(0,0,800,800)
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent)
scene = QGraphicsScene(self)
self.x_center = self.width() / 2
self.y_center = self.height() / 2
for i in range(circle_points):
angle = (360 / circle_points * i)
point = Point(angle, point_color, point_diameter, circle_diameter, self.x_center, self.y_center)
points.append(point)
scene.addItem(point)
scene.setSceneRect(0, 0, 800, 800)
self.setScene(scene)
self.setCacheMode(QGraphicsView.CacheBackground)
def main():
import sys
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Gruß
Atalanttore
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Mittwoch 5. Dezember 2018, 21:56
von __deets__
So, ich habe damit mal ein bisschen rumgespielt. Du warst schon fast da, aber der entscheidende Fehler ist mir auch erst gerade aufgefallen: du baust einen eigenen Painter. Der haengt in der Luft, tut nichts und kann nichts. Du musst stattdessen einfach nur den uebergebenen nehmen, das war's.
Code: Alles auswählen
from PyQt5.QtCore import QRectF
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsEllipseItem
from PyQt5.QtGui import QPainter, QBrush
import math
points = []
circle_points = 30
point_color = QtCore.Qt.red
point_diameter = 20
circle_diameter = 500
class Point(QGraphicsEllipseItem):
def __init__(self, angle, point_color, point_diameter, circle_diameter, x_center, y_center):
super(Point, self).__init__()
self.x_center = x_center
self.y_center = y_center
self.point_color = point_color
self.point_diameter = point_diameter
self.circle_diameter = circle_diameter
self.angle = angle
self.brush = QBrush(self.point_color)
def paint(self, painter, option, widget):
painter.setBrush(self.brush)
x = self.x_center + (self.circle_diameter / 2 * math.cos(math.radians(self.angle)))
y = self.y_center + (self.circle_diameter / 2 * math.sin(math.radians(self.angle)))
x1 = int(x - self.point_diameter)
y1 = int(y - self.point_diameter)
x2 = int(x + self.point_diameter)
y2 = int(y + self.point_diameter)
self.setRect(x1, y1, x2, y2)
painter.drawEllipse(x1, y1, x2, y2)
print("Ich werde auch ausgeführt :-)")
def boundingRect(self):
return QRectF(0,0,800,800)
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent)
scene = QGraphicsScene(self)
self.setScene(scene)
self.x_center = self.width() / 2
self.y_center = self.height() / 2
for i in range(circle_points):
angle = (360 / circle_points * i)
scene.addRect(QRectF(i * 20, i * 20, 20, 20), QtCore.Qt.red )
ellipse = QGraphicsEllipseItem((i + 1) * 20, i * 20, 20, 20)
scene.addItem(ellipse)
point = Point(angle, point_color, point_diameter, circle_diameter, self.x_center, self.y_center)
scene.addItem(point)
scene.setSceneRect(0, 0, 800, 800)
self.setCacheMode(QGraphicsView.CacheBackground)
def main():
import sys
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Mittwoch 5. Dezember 2018, 21:59
von __deets__
Nachtrag: die bounding box ist natuerlich auch komplett falsch. Die muss schon die wirklichen Koordinaten und ausmasse des Items beruecksichtigen. Und da du ableitest, kannst du auch von QGraphicsItem ableiten. Das, was eine Ellipse ausmacht, benutzt du ja gar nicht. Mein Code tut das, wie man da den Pen/Brush setzt habe ich aber noch nicht rausgefummelt. Last but not least: leite NICHT ab, benutzt die addPath-Methode.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Mittwoch 5. Dezember 2018, 22:48
von __deets__
Und hier noch ein Beispiel, welches illustriert, dass man nicht ableiten muss. Und welche Vorteile das Scene-Modell hat bei Koordinaten etc.
Code: Alles auswählen
import random
import time
from PyQt5.QtCore import QRectF
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene
from PyQt5.QtGui import QPainter, QBrush, QPainterPath
points = []
SPEED = 5000
MIN_DISTANCE = 30000
DISTANCE_VARIANCE = 20000
class Star:
D = 1000
def __init__(self, scene):
path = QPainterPath()
path.addRect(-10, -10, 20, 20)
self._x, self._y = random.random() * 20000 - 10000, random.random() * 20000 - 10000
self._z = random.random() * 20000 + MIN_DISTANCE
self._speed = random.random() * SPEED
self._path = scene.addPath(path)
self._path.setPen(QtCore.Qt.red)
def update(self, elapsed):
self._z -= elapsed * self._speed
if self._z < 0:
self._z = random.random() * DISTANCE_VARIANCE + MIN_DISTANCE
self._path.setX(self._x * self.D / self._z)
self._path.setY(self._y * self.D / self._z)
self._path.setScale(1 - self._z / (MIN_DISTANCE + DISTANCE_VARIANCE))
self._path.setRotation(self._path.rotation() + elapsed * 360)
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent)
self._last = time.monotonic()
scene = QGraphicsScene(self)
self.setScene(scene)
self.x_center = self.width() / 2
self.y_center = self.height() / 2
self._stars = []
for i in range(100):
self._stars.append(
Star(scene)
)
scene.setSceneRect(-400, -400, 800, 800)
self.setCacheMode(QGraphicsView.CacheBackground)
self._timer = QtCore.QTimer(self)
self._timer.setSingleShot(False)
self._timer.setInterval(1000 / 60)
self._timer.timeout.connect(self._update_all)
self._timer.start()
def _update_all(self):
now = time.monotonic()
elapsed = now - self._last
self._last = now
for star in self._stars:
star.update(elapsed)
def main():
import sys
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Mittwoch 5. Dezember 2018, 22:51
von Atalanttore
@__deets__: Danke für den vielen Beispielcode. Mit dem Durcharbeiten werde ich einige Zeit beschäftigt sein.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 9. Dezember 2018, 18:25
von Atalanttore
@__deets__: Ich habe mich jetzt mithilfe von Dokumentationen durchgearbeitet und mit deinem Beispielcode gespielt.
Meine Erkenntnisse und Fragen zu einzelnen Anweisungen habe ich mal als Kommentare im Beispielcode ergänzt.
Code: Alles auswählen
import random
import time
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene
from PyQt5.QtGui import QPainterPath
points = []
SPEED = 5000
MIN_DISTANCE = 30000
DISTANCE_VARIANCE = 20000
class Star:
D = 1000 # Durchmesser?
def __init__(self, scene):
path = QPainterPath() # Pfad für Kontur erstellen
path.addRect(-10, -10, 20, 20) # Kontur dem Stern zuweisen
self._x, self._y = random.random() * 20000 - 10000, random.random() * 20000 - 10000 # Zufallskoordinaten für x und y berechnen
self._z = random.random() * 20000 + MIN_DISTANCE # Zufallskoordinate für z berechnen
self._speed = random.random() * SPEED # Zufallsgeschwindigkeit berechnen
self._path = scene.addPath(path) # Pfad zur Szene hinzufügen
self._path.setPen(QtCore.Qt.red) # Farbe der Außenlinie zuweisen
def update(self, elapsed):
self._z -= elapsed * self._speed # z-Koordinate neu berechnen
if self._z < 0:
self._z = random.random() * DISTANCE_VARIANCE + MIN_DISTANCE # Zufallszahl * Multiplikator + Mindestabstand
self._path.setX(self._x * self.D / self._z) # ?
self._path.setY(self._y * self.D / self._z) # ?
self._path.setScale(1 - self._z / (MIN_DISTANCE + DISTANCE_VARIANCE)) # Sterne bei der Bewegung nach vorne größer skalieren
self._path.setRotation(self._path.rotation() + elapsed * 360) # Drehbewegung der Sterne
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent) # Programm läuft auch, wenn man kein parent übergibt
self._last = time.monotonic() # Letzte Zeit zuweisen
scene = QGraphicsScene(self) # Szene erstellen
self.setScene(scene) # QGraphicsScene dem GraphicsWindow zuweisen
# self.x_center = self.width() / 2
# self.y_center = self.height() / 2
self._stars = []
for i in range(100):
self._stars.append(
Star(scene) # 100 Star-Objekte erstellen und Liste hinzufügen
)
scene.setSceneRect(-400, -400, 800, 800) # Größe der Szene festlegen
self.setCacheMode(QGraphicsView.CacheBackground) # ?
self._timer = QtCore.QTimer(self) # QTimer-Objekt erstellen
self._timer.setSingleShot(False) # Programm läuft auch ohne diese Anweisung
self._timer.setInterval(1000 / 60) # Timer-Intervall festlegen
self._timer.timeout.connect(self._update_all) # Aktualisierungsmethode aufrufen, wenn Timer abgelaufen ist.
self._timer.start() # Timer neu starten
def _update_all(self):
now = time.monotonic() # Aktuelle Zeit zuweisen
elapsed = now - self._last # Vergangene Zeit berechnen
self._last = now # Letzte Zeit durch aktuelle Zeit ersetzen
for star in self._stars:
star.update(elapsed) # Aktualisierungsmethode jedes Star-Objektes mit vergangener Zeit aufrufen
def main():
import sys # Warum hier unten importieren?
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Gruß
Atalanttore
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 9. Dezember 2018, 19:45
von __deets__
Das mit dem sys in main musst du dich selbst fragen - von dir habe ich das ja
Ich habe das einfach uebernommen. Das ist so natuerlich Unsinn. Auch den Cache-Modus hast *du* eingefuehrt, keine Ahnung, was genau der bewirkt.
Und was deine Kommentare im allgemeinen angeht - die sind jetzt nicht so sinnvoll wie ich finde, denn sie sagen ja nur, was da steht. Zufallszahl * Multiplikator + Mindestabstand.
Viel interessanter waere zu sagen "bei negativem Z Stern wieder in der Ferne erscheinen lassen". Denn darum geht es ja.
D ist kein Durchmesser, sondern eine Konstante fuer die Perspektivische Transformation. Ich hab das so aus dem Gedaechtnis gemacht. Da koennte man jetzt mal in ein Buch zur 3D-Programmierung gucken.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 9. Dezember 2018, 20:43
von Atalanttore
@__deets__: Danke für die Antwort.
- Stammen die Formeln im Code alle aus einem Buch zur 3D-Programmierung?
- Ohne die folgenden Anweisungen läuft gar nichts mehr, aber was wird da eigentlich berechnet?
Code: Alles auswählen
self._path.setX(self._x * self.D / self._z)
self._path.setY(self._y * self.D / self._z)
- Im Ausgabefenster erscheint sowohl ein horizontaler als auch ein vertikaler Scrollbalken. Kann man die Scrollbalken auch deaktivieren?
Gruß
Atalanttore
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 9. Dezember 2018, 21:42
von __deets__
1. nein, aus meinem Kopf. So habe ich das schon auf dem AMIGA in assembler gemacht. Und da hatte ich es ggf aus einer Zeitschrift.
2. Das ist die perspektivische Transformation.
3. Bestimmt, durch Eigenschaften des Widgets. Im Designer mit rumspielen, Doku lesen. Weil aus dem Kopf weiß ich das nicht.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 16. Dezember 2018, 21:38
von Atalanttore
@__deets__:
Zu 1.: Wann hast du das letzte mal in Assembler auf dem AMIGA gearbeitet?
Zu 2.: Das ist also die Formel für die perspektivische Transformation.
Zu 3.: Welchen Codeteil in deinem Beispiel hast du mittels Qt Designer erstellt?
Gruß
Atalanttore
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 16. Dezember 2018, 22:28
von __deets__
1) Keine Ahnung, 1996 oder so. Wieso ist das wichtig?
2) das ist irgendwie keine Frage, sondern eine Feststellung...
3) Keinen. Das ist hauptsaechlich DEIN Beispiel, lediglich zum laufen gebracht. Du siehst doch, dass da keine .ui-Datei vorkommt. Oder anderweitig generiert aussieht. Der Hinweis war gemeint als "nimm dir den Designer, bau einen GraphicsView ein, und manipulier den oder das parent-widget/layout (keine Ahnung was genau), lad die UI Datei, und gucks' dir an". Der Designer prasentiert einem eben all die Layout und sonstigen Optionen auf leicht erschliessbare Art & Weise, und darum benutze ich den fuer sowas - wenn ich das selbst machen wuerde, und eben nicht nur dein Beispiel aufgebohrt haette.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 16. Dezember 2018, 22:32
von Atalanttore
@__deets__:
Zu 1.: ~22 Jahre könnte ich mir solche Details nicht im Kopf merken.
Zu 3.: Alles klar.
Gruß
Atalanttore
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Sonntag 16. Dezember 2018, 23:00
von __deets__
Naja, das ist ja eine simple Division. Du kannst dir doch sicher Dinge merken wie zb die Fläche eines Kreises zu berechnen, etc. das ist ja nichts anderes. Und es war ein ziemliches aha-Erlebnis, weil ich vorher nur einen simpleren Algorithmus kannte, der einfach jeden Stern mit fixen Schritten bewegt. Das war eher C64-Style. Darum war das so ein “wichtiges” Ding.
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Donnerstag 27. Dezember 2018, 23:54
von Atalanttore
Heute wollte ich die Sterne aus dem Beispiel blinken lassen. Dazu wollte ich zufällig entweder eine rote Außenlinie mit der Methode `setPen()` oder eine blaue Füllung mit der Methode `setBrush()` zeichnen lassen. Nun erscheinen selbst bei langsamer Geschwindigkeit blau gefüllte Rechtecke mit roter Außenlinie und nichts blinkt.
Anscheinend muss man die von `setPen()` oder `setBrush()` gezeichnete Außenlinie bzw. Füllung auch wieder löschen, wenn sie nicht mehr erscheinen soll. Leider habe ich in der Doku nichts passendes dazu gefunden.
Macht man das überhaupt so wie von mir gedacht?
Der Code:
Code: Alles auswählen
import sys
import random
import time
from random import randint
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene
from PyQt5.QtGui import QPainterPath
points = []
SPEED = 5000
MIN_DISTANCE = 30000
DISTANCE_VARIANCE = 20000
class Star:
D = 1000
def __init__(self, scene):
path = QPainterPath()
path.addRect(-10, -10, 20, 20)
self._x = random.random() * 20000 - 10000
self._y = random.random() * 20000 - 10000
self._z = random.random() * 20000 + MIN_DISTANCE
self._speed = random.random() * SPEED
self._path = scene.addPath(path)
self.draw_pen()
def draw_pen(self):
self._path.setPen(QtCore.Qt.red)
def draw_brush(self):
self._path.setBrush(QtCore.Qt.blue)
def update(self, elapsed):
self._z -= elapsed * self._speed
if self._z < 0:
self._z = random.random() * DISTANCE_VARIANCE + MIN_DISTANCE
self._path.setX(self._x * self.D / self._z)
self._path.setY(self._y * self.D / self._z)
self._path.setScale(1 - self._z / (MIN_DISTANCE + DISTANCE_VARIANCE))
self._path.setRotation(self._path.rotation() + elapsed * 360)
if randint(0, 2) == 0:
self.draw_pen()
print("Pen")
else:
self.draw_brush()
print("Brush")
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self._last = time.monotonic()
scene = QGraphicsScene(self)
self.setScene(scene)
scene.setSceneRect(-400, -400, 800, 800)
self.showFullScreen()
self._stars = []
for i in range(100):
self._stars.append(Star(scene))
self._timer = QtCore.QTimer(self)
self._timer.setInterval(1000 / 30)
self._timer.timeout.connect(self._update_all)
self._timer.start()
def _update_all(self):
now = time.monotonic()
elapsed = now - self._last
self._last = now
for star in self._stars:
star.update(elapsed)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Escape:
self.close()
def main():
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Gruß
Atalanttore
Re: Geometrische Objekte werden generiert, aber nicht angezeigt.
Verfasst: Freitag 28. Dezember 2018, 00:22
von __blackjack__
@Atalanttore: Man muss halt in beiden Fällen Pen und Brush setzen. Jeweils so dass man das eine sieht und das andere nicht. Zum Beispiel könntest Du die Farbe `Qt.transparent` für den jeweiligen Teil den man nicht sehen soll verwenden. Das würde ich allerdings nicht als blinken, sondern als flackern bezeichnen.