Version aus Leipzig
3
.gitignore
vendored
@@ -102,3 +102,6 @@ venv.bak/
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
/praezipos/docs.txt
|
||||
|
||||
/.idea/
|
||||
|
||||
14
README.md
@@ -1 +1,13 @@
|
||||
# revpi-revpiday2019
|
||||
# revpi-revpiday2019
|
||||
|
||||
Dies ist unser kleines Beispiel vom RevPiDay 2019 in Leipzig. Es ist eine Demo um Staplerfahrern die Positionierung ihrer Ladung zu erleichtern.
|
||||
|
||||
Das Projekt ist komplett in der Programmiersprache Python geschrieben und verwendet unsere Bibliothek RevPiModIO und das RevPiPyLoad system. Das Terminal und der Raspberry Pi greifen über das Netzwerk auf das Prozessabbild zu. Diese Funktion wird duch RevPiPyLoad ermöglicht.
|
||||
|
||||
Die Konfiguration besteht aus einem Profinet Gateway, einem DIO Modul, dem RevPiCore und einem virtuellen Device für die Kommunikation mit dem Terminal und dem Raspberry Pi.
|
||||
|
||||
Genauere Beschreibungen findet ihr auf unserer Seite https://revpimodio.org/revpiday2019/.
|
||||
|
||||
The "Willenbrock" logo is copyrighted by [Willenbrock Fördertechnik GmbH & Co. KG](https://www.willenbrock.de/).
|
||||
|
||||
The "Linde" logo is copyrighted by [Linde Material Handling GmbH](https://www.linde-mh.de/).
|
||||
|
||||
282
praezipos/praezipos_gui.py
Normal file
@@ -0,0 +1,282 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""GUI for forklift terminals."""
|
||||
__author__ = "Sven Sager"
|
||||
__copyright__ = "Copyright (C) 2019 Sven Sager"
|
||||
__license__ = "GPLv3"
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from revpimodio2 import RevPiNetIODriver
|
||||
from revpimodio2.netio import ConfigChanged
|
||||
|
||||
from ui.main_ui import Ui_frm_main
|
||||
|
||||
|
||||
class PraeziPos(QtWidgets.QMainWindow, Ui_frm_main):
|
||||
|
||||
def __init__(self):
|
||||
super(PraeziPos, self).__init__()
|
||||
self.setupUi(self)
|
||||
|
||||
# Setup start positions
|
||||
take_back = 550
|
||||
self.wid_fork.move(self.wid_fork.x(), self.wid_fork.y() + take_back)
|
||||
self.wid_lift.move(self.wid_lift.x(), self.wid_lift.y() + take_back)
|
||||
self.wid_load.move(self.wid_load.x(), self.wid_load.y() + take_back)
|
||||
self.wid_fork_geo = self.wid_fork.geometry()
|
||||
self.wid_lift_geo = self.wid_lift.geometry()
|
||||
self.wid_load_geo = self.wid_load.geometry()
|
||||
|
||||
# Animation thread
|
||||
self.ani = AnimatePosition(self, take_back)
|
||||
self.ani.move_forklift.connect(self.on_ani_move_forklift)
|
||||
self.ani.move_load.connect(self.on_ani_move_load)
|
||||
self.ani.start()
|
||||
|
||||
# Create revpi manager an connect thread save to events
|
||||
self.rm = RevPiManager(self)
|
||||
self.rm.forklift_changed.connect(self.on_forklift_changed)
|
||||
self.rm.load_pos_changed.connect(self.on_load_pos_changed)
|
||||
self.rm.program_running_changed.connect(self.on_program_running_changed)
|
||||
|
||||
self.status.showMessage("Verbinde zum Revolution Pi...")
|
||||
self.rm.start()
|
||||
|
||||
def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
|
||||
"""Shutdown threads before closing."""
|
||||
self.ani.requestInterruption()
|
||||
self.rm.requestInterruption()
|
||||
while self.rm.isRunning():
|
||||
self.rm.wait(100)
|
||||
|
||||
@QtCore.pyqtSlot(int)
|
||||
def on_ani_move_forklift(self, y: int):
|
||||
"""Animate the forklift."""
|
||||
self.wid_fork.setVisible(y > 0)
|
||||
self.wid_lift.setVisible(y > 0)
|
||||
|
||||
self.wid_fork.move(
|
||||
self.wid_fork.x(),
|
||||
self.wid_fork_geo.y() - y
|
||||
)
|
||||
self.wid_lift.move(
|
||||
self.wid_lift.x(),
|
||||
self.wid_lift_geo.y() - y
|
||||
)
|
||||
|
||||
@QtCore.pyqtSlot(int)
|
||||
def on_ani_move_load(self, y: int):
|
||||
"""Animate the load of forklift."""
|
||||
self.wid_load.setVisible(y > 0)
|
||||
|
||||
self.wid_load.move(
|
||||
self.wid_load.x(),
|
||||
self.wid_load_geo.y() - y
|
||||
)
|
||||
|
||||
@QtCore.pyqtSlot(str, bool)
|
||||
def on_forklift_changed(self, name: str, exists: bool):
|
||||
if exists:
|
||||
# Forklift is coming
|
||||
|
||||
self.wid_lift.move(
|
||||
self.wid_lift_geo.x() + int(self.rm.rpi.io.load_pos.value / 100),
|
||||
self.wid_lift.y()
|
||||
)
|
||||
|
||||
self.ani.come()
|
||||
else:
|
||||
# Forklift is going
|
||||
self.ani.leave()
|
||||
|
||||
@QtCore.pyqtSlot(str, int)
|
||||
def on_load_pos_changed(self, name: str, position: int):
|
||||
if not self.rm.rpi.io.program_running.value:
|
||||
return
|
||||
|
||||
if not self.rm.rpi.io.forklift.value:
|
||||
self.wid_more_left.setVisible(False)
|
||||
self.wid_more_right.setVisible(False)
|
||||
return
|
||||
|
||||
# Directions
|
||||
status = True
|
||||
if self.rm.rpi.io.more_left.value:
|
||||
status = False
|
||||
self.wid_more_left.setPixmap(QtGui.QPixmap(":/global/png/left.png"))
|
||||
|
||||
if self.rm.rpi.io.more_right.value:
|
||||
status = False
|
||||
self.wid_more_right.setPixmap(QtGui.QPixmap(":/global/png/right.png"))
|
||||
|
||||
if status:
|
||||
self.wid_more_left.setPixmap(QtGui.QPixmap(":/global/png/ok.png"))
|
||||
self.wid_more_right.setPixmap(QtGui.QPixmap(":/global/png/ok.png"))
|
||||
|
||||
self.wid_more_left.setVisible(self.rm.rpi.io.more_left.value or status)
|
||||
self.wid_more_right.setVisible(self.rm.rpi.io.more_right.value or status)
|
||||
|
||||
# Move load and fork
|
||||
self.wid_fork.move(
|
||||
self.wid_fork_geo.x() + int(position / 100),
|
||||
self.wid_fork.y()
|
||||
)
|
||||
self.wid_load.move(
|
||||
self.wid_load_geo.x() + int(position / 100),
|
||||
self.wid_load.y()
|
||||
)
|
||||
|
||||
@QtCore.pyqtSlot(str, bool)
|
||||
def on_program_running_changed(self, name: str, running: bool):
|
||||
if running:
|
||||
self.status.showMessage("Steuerprogramm läuft...", 2000)
|
||||
else:
|
||||
self.status.showMessage("Steuerprogramm ist nicht aktiv!")
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def on_btn_fullscreen_clicked(self):
|
||||
if self.isFullScreen():
|
||||
self.showNormal()
|
||||
else:
|
||||
self.showFullScreen()
|
||||
|
||||
|
||||
class AnimatePosition(QtCore.QThread):
|
||||
move_forklift = QtCore.pyqtSignal(int)
|
||||
move_load = QtCore.pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent, pixel_way: int):
|
||||
super(AnimatePosition, self).__init__(parent)
|
||||
self._come = False
|
||||
self._leave = False
|
||||
self._load_arrived = False
|
||||
self._step_time = 10
|
||||
self._step_value = 2
|
||||
self._step_wait = 1000
|
||||
|
||||
self._way = 0
|
||||
self._y_way = pixel_way
|
||||
|
||||
def come(self):
|
||||
self._leave = False
|
||||
self._come = True
|
||||
|
||||
def leave(self):
|
||||
self._come = False
|
||||
self._leave = True
|
||||
|
||||
def requestInterruption(self) -> None:
|
||||
self._come = False
|
||||
self._leave = False
|
||||
super(AnimatePosition, self).requestInterruption()
|
||||
|
||||
def run(self) -> None:
|
||||
while not self.isInterruptionRequested():
|
||||
while self._come:
|
||||
self._way += self._step_value
|
||||
|
||||
# Animation signals
|
||||
self.move_forklift.emit(self._way)
|
||||
self.move_load.emit(self._way)
|
||||
|
||||
if self._way < self._y_way:
|
||||
self._load_arrived = False
|
||||
self.msleep(self._step_time)
|
||||
else:
|
||||
self._load_arrived = True
|
||||
self._come = False
|
||||
while self._leave:
|
||||
self._way -= self._step_value
|
||||
|
||||
# Animation signals
|
||||
self.move_forklift.emit(self._way)
|
||||
if not self._load_arrived:
|
||||
self.move_load.emit(self._way)
|
||||
|
||||
if self._way > 0:
|
||||
self.msleep(self._step_wait if self._way <= self._step_value else self._step_time)
|
||||
else:
|
||||
self.move_load.emit(self._way)
|
||||
self._leave = False
|
||||
|
||||
if not (self._come or self._leave):
|
||||
self.msleep(self._step_time)
|
||||
|
||||
|
||||
class RevPiManager(QtCore.QThread):
|
||||
forklift_changed = QtCore.pyqtSignal(str, bool)
|
||||
load_pos_changed = QtCore.pyqtSignal(str, int)
|
||||
program_running_changed = QtCore.pyqtSignal(str, bool)
|
||||
|
||||
def __init__(self, parent):
|
||||
super(RevPiManager, self).__init__(parent)
|
||||
self.rpi = None # type: RevPiNetIODriver
|
||||
|
||||
def _config_rpi(self) -> None:
|
||||
"""Connect to RevPiPyLoad and register events."""
|
||||
self.rpi = RevPiNetIODriver(
|
||||
"192.168.1.2",
|
||||
"panel01",
|
||||
autorefresh=True,
|
||||
replace_io_file=":network:",
|
||||
)
|
||||
self.rpi.cycletime = 25
|
||||
self.rpi.setdefaultvalues()
|
||||
self.rpi.net_setdefaultvalues()
|
||||
|
||||
# Fire events thread save to GUI elements
|
||||
self.rpi.io.forklift.reg_event(self.forklift_changed.emit, prefire=True)
|
||||
self.rpi.io.load_pos.reg_event(self.load_pos_changed.emit, prefire=True)
|
||||
self.rpi.io.program_running.reg_event(self.program_running_changed.emit, prefire=True)
|
||||
|
||||
def run(self) -> None:
|
||||
"""Mainloop of thread to connect to RevPi and monitor status."""
|
||||
|
||||
while not self.isInterruptionRequested():
|
||||
# Connect RevPi
|
||||
if self.rpi is None:
|
||||
try:
|
||||
self._config_rpi()
|
||||
except Exception as e:
|
||||
self.msleep(250)
|
||||
continue
|
||||
|
||||
# Set values
|
||||
self.rpi.io.p_online.value = True
|
||||
|
||||
# Start event system of RevPiModIO
|
||||
try:
|
||||
self.rpi.mainloop()
|
||||
except ConfigChanged:
|
||||
# Configuration was changed, try to reconnect
|
||||
self.rpi.disconnect()
|
||||
self.rpi = None
|
||||
|
||||
# Clean up
|
||||
if self.rpi is not None:
|
||||
self.rpi.io.p_online.value = False
|
||||
self.rpi.disconnect()
|
||||
|
||||
def requestInterruption(self) -> None:
|
||||
# Just exit blocking mainloop function.
|
||||
super(RevPiManager, self).requestInterruption()
|
||||
self.rpi.exit(full=False)
|
||||
|
||||
@property
|
||||
def error(self):
|
||||
return self.rpi is None or self.rpi.reconnecting
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
app = QtWidgets.QApplication([])
|
||||
|
||||
frm_main = PraeziPos()
|
||||
if "-f" in sys.argv:
|
||||
# Show in fullscreen
|
||||
frm_main.showFullScreen()
|
||||
|
||||
frm_main.show()
|
||||
|
||||
# Run main app
|
||||
rc = app.exec_()
|
||||
sys.exit(rc)
|
||||
144
praezipos/praezipos_raspi.py
Normal file
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Praezipos system for raspberry pi with sense hat."""
|
||||
__author__ = "Sven Sager"
|
||||
__copyright__ = "Copyright (C) 2019 Sven Sager"
|
||||
__license__ = "GPLv3"
|
||||
from enum import Enum
|
||||
from revpimodio2 import RevPiNetIODriver
|
||||
from sense_hat import SenseHat
|
||||
|
||||
|
||||
class PixelColor(Enum):
|
||||
WHITE = (127, 127, 127)
|
||||
RED = (127, 0, 0)
|
||||
GREEN = (0, 127, 0)
|
||||
BLUE = (0, 0, 127)
|
||||
YELLOW = (127, 127, 0)
|
||||
BLACK = (0, 0, 0)
|
||||
|
||||
|
||||
class MyDriver:
|
||||
|
||||
def __init__(self, revpi_address: str, virtual_device: str):
|
||||
self.hat = SenseHat()
|
||||
self.px_connected = [(0, 0)]
|
||||
self.px_running = [(2, 0)]
|
||||
self.px_error = [(7, 0)]
|
||||
|
||||
self.px_center = [(i, 4) for i in range(8)]
|
||||
self.px_left3 = [(i, 1) for i in range(8)]
|
||||
self.px_left2 = [(i, 2) for i in range(8)]
|
||||
self.px_left1 = [(i, 3) for i in range(8)]
|
||||
self.px_right1 = [(i, 5) for i in range(8)]
|
||||
self.px_right2 = [(i, 6) for i in range(8)]
|
||||
self.px_right3 = [(i, 7) for i in range(8)]
|
||||
|
||||
self.mrk_pos = None
|
||||
|
||||
# Connect to RevPiModIO
|
||||
self.rpi = RevPiNetIODriver(
|
||||
revpi_address, virtual_device,
|
||||
autorefresh=True,
|
||||
monitoring=True,
|
||||
replace_io_file=":network:",
|
||||
)
|
||||
self.rpi.handlesignalend(self.stop)
|
||||
|
||||
def _set_px(self, pixels: list, color: PixelColor):
|
||||
"""Global function to set a pixel map."""
|
||||
for pixel in pixels:
|
||||
self.hat.set_pixel(*pixel, color.value)
|
||||
|
||||
def on_load_pos(self, name: str, value: int):
|
||||
if not self.rpi.io.program_running.value:
|
||||
return
|
||||
|
||||
if self.rpi.io.forklift.value:
|
||||
status = True
|
||||
pos_px = None
|
||||
if self.rpi.io.more_left:
|
||||
status = False
|
||||
if value < 2000:
|
||||
pos_px = self.px_right1
|
||||
elif value < 4000:
|
||||
pos_px = self.px_right2
|
||||
else:
|
||||
pos_px = self.px_right3
|
||||
|
||||
if self.rpi.io.more_right:
|
||||
status = False
|
||||
print(value)
|
||||
if value < -4000:
|
||||
pos_px = self.px_left3
|
||||
elif value < -2000:
|
||||
pos_px = self.px_left2
|
||||
else:
|
||||
pos_px = self.px_left1
|
||||
|
||||
if self.mrk_pos != pos_px:
|
||||
# Switch off old pixel
|
||||
if self.mrk_pos:
|
||||
self._set_px(self.mrk_pos, PixelColor.BLACK)
|
||||
|
||||
# Switch on new pixel
|
||||
if pos_px:
|
||||
self._set_px(pos_px, PixelColor.RED)
|
||||
|
||||
self.mrk_pos = pos_px
|
||||
|
||||
# Show center line
|
||||
self._set_px(
|
||||
self.px_center,
|
||||
PixelColor.GREEN if status else PixelColor.BLUE
|
||||
)
|
||||
|
||||
else:
|
||||
self._set_px(self.px_center, PixelColor.BLACK)
|
||||
if self.mrk_pos:
|
||||
self._set_px(self.mrk_pos, PixelColor.BLACK)
|
||||
|
||||
def on_program_running(self, name, value):
|
||||
self._set_px(self.px_running, PixelColor.GREEN if value else PixelColor.YELLOW)
|
||||
|
||||
def start(self):
|
||||
|
||||
self.rpi.io.program_running.reg_event(self.on_program_running, prefire=True)
|
||||
self.rpi.io.load_pos.reg_event(self.on_load_pos, prefire=True)
|
||||
|
||||
self.rpi.mainloop(blocking=False)
|
||||
|
||||
while not self.rpi.exitsignal.wait(0.2):
|
||||
self._set_px(
|
||||
self.px_connected,
|
||||
PixelColor.RED if self.rpi.reconnecting else PixelColor.GREEN
|
||||
)
|
||||
|
||||
# Check for errors
|
||||
if self.rpi.ioerrors > 0:
|
||||
self.rpi.resetioerrors()
|
||||
self._set_px(self.px_error, PixelColor.RED)
|
||||
else:
|
||||
self._set_px(self.px_error, PixelColor.GREEN)
|
||||
|
||||
self.hat.clear()
|
||||
self.rpi.disconnect()
|
||||
|
||||
def stop(self):
|
||||
self.rpi.setdefaultvalues()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from time import sleep
|
||||
|
||||
root = None
|
||||
while root is None:
|
||||
try:
|
||||
while True:
|
||||
root = MyDriver("192.168.1.2", "panel01")
|
||||
root.start()
|
||||
if not root.rpi.config_changed:
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sleep(5)
|
||||
81
praezipos/praezipos_revpi.py
Normal file
@@ -0,0 +1,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Forklift load navigator."""
|
||||
__author__ = "Sven Sager"
|
||||
__copyright__ = "Copyright (C) 2019 Sven Sager"
|
||||
__license__ = "GPLv3"
|
||||
import revpimodio2
|
||||
from random import randint
|
||||
from revpimodio2.helper import Cycletools
|
||||
|
||||
|
||||
def cycle(ct: Cycletools):
|
||||
if ct.first:
|
||||
# Init control program variables
|
||||
ct.var.center_diff_left = -600
|
||||
ct.var.center_diff_right = 600
|
||||
ct.var.center_value = 0
|
||||
ct.var.mrk_t_forklift = False
|
||||
|
||||
rpi.io.program_running.value = True
|
||||
|
||||
# Flash LED A1 of core module
|
||||
rpi.core.a1green.value = ct.flag20c
|
||||
|
||||
if rpi.io.t_forklift.value:
|
||||
# Forklift in place
|
||||
rpi.io.forklift.value = True
|
||||
|
||||
if not ct.var.mrk_t_forklift:
|
||||
ct.var.mrk_t_forklift = True
|
||||
ct.var.center_value = rpi.io.position.value + randint(-6000, 6000)
|
||||
|
||||
position = rpi.io.position.value - ct.var.center_value
|
||||
|
||||
# Mirror value to virtual device
|
||||
rpi.io.load_pos.value = position
|
||||
|
||||
# Check direction of difference
|
||||
rpi.io.more_right.value = position < ct.var.center_diff_left
|
||||
rpi.io.more_left.value = position > ct.var.center_diff_right
|
||||
|
||||
# Show lights
|
||||
rpi.io.h_red.value = rpi.io.more_left.value or rpi.io.more_right.value
|
||||
rpi.io.h_green.value = not rpi.io.h_red.value
|
||||
|
||||
else:
|
||||
# No forklift in position
|
||||
ct.var.mrk_t_forklift = False
|
||||
|
||||
rpi.io.forklift.value = False
|
||||
rpi.io.load_pos.value = 0
|
||||
rpi.io.more_left.value = False
|
||||
rpi.io.more_right.value = False
|
||||
rpi.io.h_red.value = False
|
||||
rpi.io.h_green.value = False
|
||||
|
||||
|
||||
def cleanup():
|
||||
rpi.io.program_running.value = False
|
||||
|
||||
|
||||
# One global RevPiModIO instance for all modules and classes
|
||||
rpi = revpimodio2.RevPiModIO(autorefresh=True)
|
||||
|
||||
# Configure IO of profinet device
|
||||
rpi.io.b_position1.replace_io("position", "H", byteorder="big")
|
||||
|
||||
# Configure IO of panel device
|
||||
rpi.io.p_byte1.replace_io("p_online", "?", bit=0)
|
||||
|
||||
rpi.io.r_byte1.replace_io("program_running", "?", bit=0)
|
||||
rpi.io.r_byte2.replace_io("more_left", "?", bit=0)
|
||||
rpi.io.r_byte2.replace_io("more_right", "?", bit=1)
|
||||
rpi.io.r_byte2.replace_io("forklift", "?", bit=2)
|
||||
|
||||
rpi.io.r_position1.replace_io("load_pos", "h")
|
||||
|
||||
# Export replaced ios for revpipyload and NetIO clients
|
||||
rpi.export_replaced_ios()
|
||||
|
||||
rpi.handlesignalend(cleanup)
|
||||
rpi.cycleloop(cycle, cycletime=20)
|
||||
5
praezipos/ui/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""UI of forklift terminal GUI."""
|
||||
__author__ = "Sven Sager"
|
||||
__copyright__ = "Copyright (C) 2019 Sven Sager"
|
||||
__license__ = "GPLv3"
|
||||
14428
praezipos/ui/main_rc.py
Normal file
101
praezipos/ui/main_ui.py
Normal file
@@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'main.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.10.1
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_frm_main(object):
|
||||
def setupUi(self, frm_main):
|
||||
frm_main.setObjectName("frm_main")
|
||||
frm_main.resize(1024, 768)
|
||||
frm_main.setMinimumSize(QtCore.QSize(1024, 768))
|
||||
self.centralwidget = QtWidgets.QWidget(frm_main)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
|
||||
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout.setSpacing(0)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.lbl_header = QtWidgets.QLabel(self.centralwidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.lbl_header.sizePolicy().hasHeightForWidth())
|
||||
self.lbl_header.setSizePolicy(sizePolicy)
|
||||
self.lbl_header.setText("")
|
||||
self.lbl_header.setPixmap(QtGui.QPixmap(":/global/img/willebg.png"))
|
||||
self.lbl_header.setScaledContents(True)
|
||||
self.lbl_header.setObjectName("lbl_header")
|
||||
self.verticalLayout.addWidget(self.lbl_header)
|
||||
self.wid_main = QtWidgets.QWidget(self.centralwidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.wid_main.sizePolicy().hasHeightForWidth())
|
||||
self.wid_main.setSizePolicy(sizePolicy)
|
||||
self.wid_main.setObjectName("wid_main")
|
||||
self.frame_center = QtWidgets.QFrame(self.wid_main)
|
||||
self.frame_center.setGeometry(QtCore.QRect(350, 20, 324, 200))
|
||||
self.frame_center.setFrameShape(QtWidgets.QFrame.Panel)
|
||||
self.frame_center.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||
self.frame_center.setLineWidth(15)
|
||||
self.frame_center.setObjectName("frame_center")
|
||||
self.wid_load = QtWidgets.QLabel(self.wid_main)
|
||||
self.wid_load.setGeometry(QtCore.QRect(350, 20, 324, 215))
|
||||
self.wid_load.setPixmap(QtGui.QPixmap(":/global/img/load.png"))
|
||||
self.wid_load.setObjectName("wid_load")
|
||||
self.wid_lift = QtWidgets.QLabel(self.wid_main)
|
||||
self.wid_lift.setGeometry(QtCore.QRect(354, 280, 316, 432))
|
||||
self.wid_lift.setPixmap(QtGui.QPixmap(":/global/img/lift.png"))
|
||||
self.wid_lift.setObjectName("wid_lift")
|
||||
self.wid_fork = QtWidgets.QLabel(self.wid_main)
|
||||
self.wid_fork.setGeometry(QtCore.QRect(404, -13, 216, 293))
|
||||
self.wid_fork.setPixmap(QtGui.QPixmap(":/global/img/fork.png"))
|
||||
self.wid_fork.setObjectName("wid_fork")
|
||||
self.wid_more_left = QtWidgets.QLabel(self.wid_main)
|
||||
self.wid_more_left.setGeometry(QtCore.QRect(100, 50, 128, 128))
|
||||
self.wid_more_left.setPixmap(QtGui.QPixmap(":/global/png/left.png"))
|
||||
self.wid_more_left.setObjectName("wid_more_left")
|
||||
self.wid_more_right = QtWidgets.QLabel(self.wid_main)
|
||||
self.wid_more_right.setGeometry(QtCore.QRect(796, 50, 128, 128))
|
||||
self.wid_more_right.setPixmap(QtGui.QPixmap(":/global/png/right.png"))
|
||||
self.wid_more_right.setObjectName("wid_more_right")
|
||||
self.btn_fullscreen = QtWidgets.QPushButton(self.wid_main)
|
||||
self.btn_fullscreen.setGeometry(QtCore.QRect(0, 0, 50, 50))
|
||||
self.btn_fullscreen.setText("")
|
||||
self.btn_fullscreen.setFlat(True)
|
||||
self.btn_fullscreen.setObjectName("btn_fullscreen")
|
||||
self.frame_center.raise_()
|
||||
self.wid_lift.raise_()
|
||||
self.wid_fork.raise_()
|
||||
self.wid_more_left.raise_()
|
||||
self.wid_more_right.raise_()
|
||||
self.wid_load.raise_()
|
||||
self.btn_fullscreen.raise_()
|
||||
self.verticalLayout.addWidget(self.wid_main)
|
||||
frm_main.setCentralWidget(self.centralwidget)
|
||||
self.status = QtWidgets.QStatusBar(frm_main)
|
||||
self.status.setObjectName("status")
|
||||
frm_main.setStatusBar(self.status)
|
||||
|
||||
self.retranslateUi(frm_main)
|
||||
QtCore.QMetaObject.connectSlotsByName(frm_main)
|
||||
|
||||
def retranslateUi(self, frm_main):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
frm_main.setWindowTitle(_translate("frm_main", "PIO"))
|
||||
|
||||
from . import main_rc
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
frm_main = QtWidgets.QMainWindow()
|
||||
ui = Ui_frm_main()
|
||||
ui.setupUi(frm_main)
|
||||
frm_main.show()
|
||||
sys.exit(app.exec_())
|
||||
|
||||
BIN
praezipos/ui_dev/img/fork.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
praezipos/ui_dev/img/lift.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
praezipos/ui_dev/img/load.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
praezipos/ui_dev/img/willebg.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
12
praezipos/ui_dev/main.qrc
Normal file
@@ -0,0 +1,12 @@
|
||||
<RCC>
|
||||
<qresource prefix="global">
|
||||
<file>img/load.png</file>
|
||||
<file>img/fork.png</file>
|
||||
<file>img/lift.png</file>
|
||||
<file>img/willebg.png</file>
|
||||
<file>png/left.png</file>
|
||||
<file>png/ok.png</file>
|
||||
<file>png/right.png</file>
|
||||
<file>png/fail.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
183
praezipos/ui_dev/main.ui
Normal file
@@ -0,0 +1,183 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>frm_main</class>
|
||||
<widget class="QMainWindow" name="frm_main">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1024</width>
|
||||
<height>768</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1024</width>
|
||||
<height>768</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>PIO</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_header">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="main.qrc">:/global/img/willebg.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="wid_main" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_center">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>350</x>
|
||||
<y>20</y>
|
||||
<width>324</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>15</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="wid_load">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>350</x>
|
||||
<y>20</y>
|
||||
<width>324</width>
|
||||
<height>215</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="main.qrc">:/global/img/load.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="wid_lift">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>354</x>
|
||||
<y>280</y>
|
||||
<width>316</width>
|
||||
<height>432</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="main.qrc">:/global/img/lift.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="wid_fork">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>404</x>
|
||||
<y>-13</y>
|
||||
<width>216</width>
|
||||
<height>293</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="main.qrc">:/global/img/fork.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="wid_more_left">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>100</x>
|
||||
<y>50</y>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="main.qrc">:/global/png/left.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="wid_more_right">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>796</x>
|
||||
<y>50</y>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="main.qrc">:/global/png/right.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btn_fullscreen">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<zorder>frame_center</zorder>
|
||||
<zorder>wid_lift</zorder>
|
||||
<zorder>wid_fork</zorder>
|
||||
<zorder>wid_more_left</zorder>
|
||||
<zorder>wid_more_right</zorder>
|
||||
<zorder>wid_load</zorder>
|
||||
<zorder>btn_fullscreen</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="status"/>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="main.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
BIN
praezipos/ui_dev/png/fail.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
praezipos/ui_dev/png/left.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
praezipos/ui_dev/png/ok.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
praezipos/ui_dev/png/right.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |