I am working on a game in which I have completed the engine and the networking layers. I am now working on some GUI for the game using PyQt5 (as the drawing isn't complex). I made a custom QWidget for drawing the game board which is just a widget that positions custom QPushButtons inside itself. Here's the code for that:
class BoardButton(QtWidgets.QPushButton):
tilePressed = pyqtSignal(Tile)
def __init__(self, tile: Tile = None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setAutoFillBackground(True)
self.setCheckable(False)
self.setDefault(False)
self.setFlat(False)
self.raise_()
self.tile = tile
self.default_background(tile)
self.highlight = False
self.is_clicked = False
def __change_bgd(self, colour):
p = self.palette()
p.setColor(self.backgroundRole(), colour)
self.setPalette(p)
def default_background(self, tile: Tile):
if tile == self.tile:
self.__change_bgd(QtGui.QColor(153, 76, 0))
def highlight_background(self, tile: Tile):
if tile == self.tile:
self.__change_bgd(QtCore.Qt.green)
def mousePressEvent(self, e: QtGui.QMouseEvent) -> None:
self.tilePressed.emit(self.tile)
def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
if self.highlight:
self.highlight_background(self.tile)
else:
self.default_background(self.tile)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
painter.setPen(QtGui.QPen(QtCore.Qt.black, QtCore.Qt.SolidLine))
painter.drawRect(0, 0, self.width(), self.height())
if self.tile:
if self.tile.is_special:
first_line = self.width() / 3
second_line = first_line * 2
painter.drawLine(first_line, 0, first_line, self.height())
painter.drawLine(second_line, 0, second_line, self.height())
painter.drawLine(0, first_line, self.width(), first_line)
painter.drawLine(0, second_line, self.width(), second_line)
if self.tile.is_exit:
painter.setBrush(QtCore.Qt.NoBrush)
painter.drawEllipse(self.width() / 4, self.height() / 4, self.width() / 2, self.height() / 2)
if self.tile.piece is not None:
if self.tile.piece.is_white:
colour = QtCore.Qt.white
else:
colour = QtCore.Qt.black
painter.setBrush(QtGui.QBrush(colour, QtCore.Qt.SolidPattern))
painter.drawEllipse(0, 0, self.width(), self.height())
if self.tile.piece.is_king:
painter.setBrush(QtGui.QBrush(QtCore.Qt.white, QtCore.Qt.SolidPattern))
painter.drawEllipse(self.width() / 4, self.height() / 4, self.width() / 2, self.height() / 2)
class GameBoard(QtWidgets.QWidget):
tilePressed = pyqtSignal(Tile)
boardUpdate = pyqtSignal()
def __init__(self, game: Game = None, is_white: bool = None, playable=True, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setGeometry(QtCore.QRect(20, 20, 650, 650))
self.setObjectName("boardWidget")
self.game = game
self.is_white = is_white
self.playable = playable
self.buttons = []
self.__selected = None
self.tilePressed.connect(self.__tile_pressed)
def init_buttons(self):
def pos_to_name(x, y):
return f'btn_{x}{y}'
self.buttons = []
board = self.game.board
board_size = board.width
if board.width > board.height:
board_size = board.width
elif board.width < board.height:
board_size = board.height
btn_size = self.width() / board_size
start_x = self.width() / 2 - btn_size * (board.width / 2)
start_y = self.height() / 2 - btn_size * (board.height / 2)
for y in range(board.height):
row = []
for x in range(board.width):
button = BoardButton(board[y][x], parent=self)
button.setGeometry(QtCore.QRect(start_x + x * btn_size, start_y + y * btn_size, btn_size, btn_size))
button.setObjectName(pos_to_name(x, y))
button.tilePressed.connect(self.tilePressed.emit)
row.append(button)
self.buttons.append(row)
def __get_button(self, tile: Tile) -> BoardButton:
return self.buttons[tile.y][tile.x]
def update(self) -> None:
self.boardUpdate.emit()
for y, row in enumerate(self.buttons):
for x, button in enumerate(row):
button.tile = self.game.board[y][x]
button.update()
super().update()
def remove_highlights(self):
self.__selected = None
for row in self.buttons:
for button in row:
button.highlight = False
button.is_clicked = False
def highlight_buttons(self, source_tile: Tile):
self.__selected = source_tile
for tile in self.game.board.valid_moves(source_tile):
self.buttons[tile.y][tile.x].highlight = True
def move_piece(self, target_tile: Tile):
if not self.__selected:
raise ValueError('Cannot move piece because no piece is selected.')
self.game.move(self.__selected, target_tile)
def is_highlight(self, tile: Tile) -> bool:
return self.__get_button(tile).highlight
def is_clicked(self, tile: Tile) -> bool:
return self.__get_button(tile).is_clicked
def set_clicked(self, tile: Tile, value: bool):
self.__get_button(tile).is_clicked = value
def __tile_pressed(self, tile: Tile):
if not tile or self.game.game_over or not self.playable:
return
if self.is_white is not None and not is_turn(self.is_white, self.game):
return
if not tile.piece and self.is_highlight(tile):
try:
self.move_piece(tile)
except (BoardGameException, Win):
pass
self.remove_highlights()
elif not tile.piece and not self.is_highlight(tile):
self.remove_highlights()
elif tile.piece:
if self.is_clicked(tile):
self.remove_highlights()
elif self.game.is_turn(tile):
self.remove_highlights()
self.highlight_buttons(tile)
self.set_clicked(tile, True)
self.update()
This code works perfectly with one of my windows:
class LocalGameWindow(Ui_FrmLocalGame):
def __init__(self, game, playable=True):
super().__init__(game=game, playable=playable)
self.init_gameboard()
self.gameboard.update()
if self.gameboard.playable:
self.btnUndo.clicked.connect(self.btn_undo_clicked)
else:
self.setWindowTitle(...)
self.btnUndo.setText('Play')
self.lblTurn.setVisible(False)
self.lblBlackPieces.setVisible(False)
self.lblWhitePieces.setVisible(False)
self.btnExit.clicked.connect(self.close)
def btn_undo_clicked(self):
self.gameboard.game.undo()
self.gameboard.update()
Which inherits from the following (Ui_FrmLocalGame was generated with Qt Designer):
class Ui_FrmLocalGame(_GameBoardWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setupUi(self)
def setupUi(self, FrmLocalGame):
...
Which in turn inherits from:
class _GameBoardWindow(GameWidget):
def __init__(self, client: Client = None, *args, **kwargs):
super().__init__()
is_white = None
if client:
is_white = client.is_white
self.gameboard = GameBoard(is_white=is_white, *args, **kwargs, parent=self)
self.client = client
self.gameboard.boardUpdate.connect(self.update_labels)
def init_gameboard(self, game: Game = None):
if game:
self.gameboard.game = game
self.gameboard.init_buttons()
def update_labels(self):
game = self.gameboard.game
if not game:
return
if not game.game_over:
text = f"{'Black' if game.black.is_turn else 'White'}'s Turn"
else:
text = f"{'Black' if game.black.won else 'White'} Won!"
self.lblTurn.setText(text)
self.lblBlackPieces.setText(f'Black: {game.board.num_black}/{game.board.num_start_black}')
self.lblWhitePieces.setText(f'White: {game.board.num_white}/{game.board.num_start_white}')
This gives me the result I expect, it draws the gameboard widget on the window widget:
However, when I try to do seemingly the same thing with a different window widget (the online window), it just doesn't appear on the window as it does with the local game window. Here's the code for the window:
class Ui_FrmOnlineGame(_GameBoardWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setupUi(self)
def setupUi(self, FrmOnlineGame):
...
class OnlineGameWindow(Ui_FrmOnlineGame):
def __init__(self, client: Client):
super().__init__(client=client)
self.btnSend.clicked.connect(self.btn_send_clicked)
self.txtChat.returnPressed.connect(self.btn_send_clicked)
self.btnExit.clicked.connect(self.close)
self.__timer = QtCore.QTimer(self)
self.__timer.setInterval(100)
self.__timer.timeout.connect(self.__game_loop)
self.__timer.start()
def __game_loop(self):
try:
msg = self.client.recv_msg()
except BlockingIOError:
return
...
elif msg.startswith(Message.GameUpdate.value):
game = Game.from_serial(msg[1:])
self.gameboard.game = game
if not len(self.gameboard.buttons):
self.init_gameboard()
self.gameboard.update() # This should draw the gameboard widget like it does on the other window
...
def display_chat(self, text: str):
...
def display_colour(self):
show_dialog(f"You are {'white' if self.client.is_white else 'black'}.", self, 'Game Start', modal=False)
def btn_send_clicked(self):
...
def close(self) -> bool:
self.__timer.stop()
self.client.exit()
return super().close()
I've tried many things such as checking the custom widget's geometry, raising it, and making sure that it does have a parent (which it does). What have I done wrong? Any help would be appreciated, and sorry about all the code, I just feel it's necessary to find the issue.
Related
I'm trying to draw a line interactively but I can't figure out how to do it. Anyone can help me?
I'm using PyQt5. I create a QGraphicsScene, I override mouse press event but when I try to draw the draw the it draw nothing.
Finally, I have another question. How can I snap this line to the grid?
import math
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class neGraphicScene(QGraphicsScene):
_colorBackGround: str
_colorLightLines: str
_colorDarkLines: str
_penLight: QPen
_penDark: QPen
gridSize: int = 20
gridSquares: int = 5
isLineDrawing = False
def __init__(self, parent=None):
QGraphicsScene.__init__(self, QRectF(-1000, -1000, 2000, 2000), parent)
self.setSceneColor()
self.begin, self.destination = QPoint(), QPoint()
def setSceneColor(self, _lightLines="#2f2f2f", _darkLines="#292929", _background="#393939"):
self._colorBackGround = _background
self._colorLightLines = _lightLines
self._colorDarkLines = _darkLines
self._penLight = QPen(QColor(self._colorLightLines))
self._penLight.setWidth(1)
self._penDark = QPen(QColor(self._colorDarkLines))
self._penDark.setWidth(2)
self.setBackgroundBrush(QColor(self._colorBackGround))
def setGraphicScene(self, width, height):
self.setSceneRect(-width // 2, -height // 2, width, height)
def mouseDoubleClickEvent(self, event):
QGraphicsScene.mouseMoveEvent(self, event)
def mousePressEvent(self, event):
self.isLineDrawing = True
if event.buttons() & Qt.LeftButton:
print('Point 1')
self.begin = event.pos()
self.destination = self.begin
self.update()
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
print('Point 2')
self.destination = event.pos()
self.update()
def mouseReleaseEvent(self, event):
self.isLineDrawing = False
print('Point 3')
def drawBackground(self, painter, rect):
super(neGraphicScene, self).drawBackground(painter, rect)
# self.drawBackgroundGrid(painter, rect)
if self.isLineDrawing:
if not self.begin.isNull() and not self.destination.isNull():
line = QLineF(self.begin, self.destination)
painter.setPen(Qt.red)
painter.drawLine(line)
This is the QGraphicsView and the QWidgetStuff to made the minimal example working properly:
class neGraphicView(QGraphicsView):
def __init__(self, graphicScene, parent=None):
super().__init__(parent)
# self._dragPos = QPoint(0, 0)
self.sharedGraphicScene = graphicScene
self.setScene(self.sharedGraphicScene)
self._mousePressed = False
self._isPanning = False
self.initUI()
def initUI(self):
self.setRenderHints(
QPainter.Antialiasing | QPainter.HighQualityAntialiasing |
QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setDragMode(QGraphicsView.RubberBandDrag)
class NodeEditorWindow(QWidget):
mainLayout: QVBoxLayout
mainGraphicsScene: neGraphicScene
view: neGraphicView
def __init__(self, parent=None):
super(NodeEditorWindow, self).__init__(parent)
self.initUI()
def initUI(self):
self.setGeometry(200, 200, 800, 600)
self.mainLayout = QVBoxLayout()
self.mainLayout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.mainLayout)
self.mainGraphicsScene = neGraphicScene()
self.view = neGraphicView(self.mainGraphicsScene, self)
self.mainLayout.addWidget(self.view)
self.setWindowTitle("Node Editor")
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle("Fusion")
win = NodeEditorWindow()
win.show()
sys.exit(app.exec())
This is the grid function:
def drawBackgroundGrid(self, _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)
try:
# compute all lines to be drawn
lightLines, darkLines = [], []
for x in range(first_left, _right, self.gridSize):
if x % (self.gridSize * self.gridSquares) != 0:
lightLines.append(QLineF(x, _top, x, _bottom))
else:
darkLines.append(QLineF(x, _top, x, _bottom))
for y in range(first_top, _bottom, self.gridSize):
if y % (self.gridSize * self.gridSquares) != 0:
lightLines.append(QLineF(_left, y, _right, y))
else:
darkLines.append(QLineF(_left, y, _right, y))
# draw the lines
_painter.setPen(self._penLight)
_painter.drawLines(*lightLines)
_painter.setPen(self._penDark)
_painter.drawLines(*darkLines)
except Exception as e:
# print(e)
pass
I have a memory game made with python and tkinter. I've also made an application with a simple GUI that uses tk.Frame to show different frames. My problem is putting the memory game in one of the frames of the GUI app.
I have one .py file for the memory game and one for the GUI. The GUI has multiple classes and frames. I want to put the memory game inside one of those frames so that you can navigate through the menu into the game. The game should only show when navigated to.
I have tried:
importing the memorygame file at the top of the GUI file
importing the memorygame file inside a class of the GUI file
copying the whole memorygame code into a class of the GUI file
Importing the file made both the applications try to run on startup in different windows. Copying the game code into a GUI class gave lots of errors.
I have python 3.7 and tkinter 8.6
The memory game starts by creating a canvas that it draws upon:
win = tk.Tk()
canvas = tk.Canvas(win, width = 600, height = 480)
canvas.pack()
class Tile(object):
def __init__(self, x, y, text):
self.y = y
self.x = x
self.text = text
def drawFaceDown(self):
canvas.create_rectangle(self.x, self.y, self.x + 100, self.y + 100, fill = "green")
...
And this is how I use a class to create a frame where I display different things:
class PageMG(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# memory game goes here
I can show the entire files if anyone wants to see
I want the game to only show until I click on a button that takes me to the frame where I want the game.
Edit: the whole memory game file
import tkinter as tk
import time
from random import randint
from random import shuffle
win = tk.Tk()
canvas = tk.Canvas(win, width = 500, height = 500)
canvas.pack()
class Tile(object):
def __init__(self, x, y, text):
self.y = y
self.x = x
self.text = text
def drawFaceDown(self):
canvas.create_rectangle(self.x, self.y, self.x + 70, self.y + 70, fill = "blue")
self.isFaceUp = False
def drawFaceUp(self):
canvas.create_rectangle(self.x, self.y, self.x + 70, self.y + 70, fill = "blue")
canvas.create_text(self.x + 35, self.y + 35, text = self.text, width = 70, fill = "white", font='Helvetica 12 bold')
self.isFaceUp = True
def isUnderMouse(self, event):
if(event.x > self.x and event.x < self.x + 70):
if(event.y > self.y and event.y < self.y + 70):
return True
tiles = []
colors = [
"Eple",
"Appelsin",
"Banan",
"Agurk",
"Brokkoli",
"Tomat",
"Sitron",
"Melon",
"Hvitløk",
"Erter",
"Jordbær",
"Blåbær"
]
selected = []
for i in range(10):
randomInd = randint(0, len(colors) - 1)
color = colors[randomInd]
selected.append(color)
selected.append(color)
del colors[randomInd]
shuffle(selected)
flippedTiles = []
def mouseClicked(self):
global numFlipped
global flippedTiles
for i in range(len(tiles)):
if tiles[i].isUnderMouse(self):
if (len(flippedTiles) < 2 and not(tiles[i].isFaceUp)) :
tiles[i].drawFaceUp()
flippedTiles.append(tiles[i])
if (len(flippedTiles) == 2):
if not(flippedTiles[0].text == flippedTiles[1].text):
time.sleep(1)
flippedTiles[0].drawFaceDown()
flippedTiles[1].drawFaceDown()
NUM_COLS = 5
NUM_ROWS = 4
for x in range(0,NUM_COLS):
for y in range(0,NUM_ROWS):
tiles.append(Tile(x * 78 + 10, y * 78 + 40, selected.pop()))
for i in range(len(tiles)):
tiles[i].drawFaceDown()
flippedThisTurn = 0
def mouseClicked(event):
global flippedTiles
global flippedThisTurn
for tile in tiles:
if tile.isUnderMouse(event):
if (not(tile.isFaceUp)) :
tile.drawFaceUp()
flippedTiles.append(tile)
flippedThisTurn += 1
if (flippedThisTurn == 2):
win.after(1000, checkTiles)
flippedThisTurn = 0
def checkTiles():
if not(flippedTiles[-1].text == flippedTiles[-2].text): #check last two elements
flippedTiles[-1].drawFaceDown() #facedown last two elements
flippedTiles[-2].drawFaceDown()
del flippedTiles[-2:] #remove last two elements
win.bind("<Button-1>", mouseClicked)
win.mainloop()
importing the memorygame file at the top of the GUI file
importing the memorygame file inside a class of the GUI file
Both these ways will make "both the applications try to run on startup in different windows" this is because the memorygame file makes a new tk.Tk() window, and so does your GUI handler.
copying the whole memorygame code into a class of the GUI file
This could cause many problems, depending where you copy the files to, since these files have their own import dependencies and the import paths may change depending where you copy the files to.
What I would suggest doing is the following, I would change your code of the memory game to make the memory game a class(tk.Frame) (Frame class), then you should be able to import the memory game and stick that frame into the GUI PageMk(tk.Frame), I do not know the dependencies your code has, but this should work.
Example of change using the provided code
class MemGame(tk.Frame):
def __init__(self, parent):
super(MemGame, self).__init__(parent)
self.configure(width=600, height=480)
canvas = tk.Canvas(self, width=600, height=480, bg="red")
canvas.pack()
class Tile:
def __init__(self, parent, x, y, text):
self.parent = parent
self.y = y
self.x = x
self.text = text
def drawFaceDown(self):
self.parent.create_rectangle(self.x, self.y, self.x + 100, self.y + 100, fill="green")
class PageMG(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
x = MemGame(self)
x.pack()
My Edits to the full code:
import tkinter as tk
import time
from random import randint
from random import shuffle
class Controller(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
if True:
self.frames = {}
for F in (PageMG,):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("PageMG")
self.geometry("500x400")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class PageMG(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
x = MemGame(self)
x.pack()
class Tile(object):
def __init__(self, canvas, x, y, text):
self.canvas = canvas
self.y = y
self.x = x
self.text = text
def drawFaceDown(self):
self.canvas.create_rectangle(self.x, self.y, self.x + 70, self.y + 70, fill = "blue")
self.isFaceUp = False
def drawFaceUp(self):
self.canvas.create_rectangle(self.x, self.y, self.x + 70, self.y + 70, fill = "blue")
self.canvas.create_text(self.x + 35, self.y + 35, text = self.text, width = 70, fill = "white", font='Helvetica 12 bold')
self.isFaceUp = True
def isUnderMouse(self, event):
if(event.x > self.x and event.x < self.x + 70):
if(event.y > self.y and event.y < self.y + 70):
return True
class MemGame(tk.Frame):
def __init__(self, master):
super(MemGame, self).__init__(master)
self.configure(width=500, height=500)
self.canvas = tk.Canvas(self, width=500, height=500)
self.canvas.pack()
self.tiles = []
self.colors = [
"Eple",
"Appelsin",
"Banan",
"Agurk",
"Brokkoli",
"Tomat",
"Sitron",
"Melon",
"Hvitløk",
"Erter",
"Jordbær",
"Blåbær"
]
selected = []
for i in range(10):
randomInd = randint(0, len(self.colors) - 1)
color = self.colors[randomInd]
selected.append(color)
selected.append(color)
del self.colors[randomInd]
shuffle(selected)
self.flippedTiles = []
NUM_COLS = 5
NUM_ROWS = 4
for x in range(0, NUM_COLS):
for y in range(0, NUM_ROWS):
self.tiles.append(Tile(self.canvas, x * 78 + 10, y * 78 + 40, selected.pop()))
for i in range(len(self.tiles)):
self.tiles[i].drawFaceDown()
self.flippedThisTurn = 0
self.bind("<Button-1>", self.mouseClicked)
# def mouseClicked(self):
# for i in range(len(self.tiles)):
# if self.tiles[i].isUnderMouse(self):
# if (len(self.flippedTiles) < 2 and not(self.tiles[i].isFaceUp)) :
# self.tiles[i].drawFaceUp()
# self.flippedTiles.append(self.tiles[i])
# if (len(self.flippedTiles) == 2):
# if not(self.flippedTiles[0].text == self.flippedTiles[1].text):
# time.sleep(1)
# self.flippedTiles[0].drawFaceDown()
# self.flippedTiles[1].drawFaceDown()
def mouseClicked(self, event):
for tile in self.tiles:
if tile.isUnderMouse(event):
if (not(tile.isFaceUp)) :
tile.drawFaceUp()
self.flippedTiles.append(tile)
self.flippedThisTurn += 1
if (self.flippedThisTurn == 2):
self.after(1000, self.checkTiles)
self.flippedThisTurn = 0
def checkTiles(self):
if not(self.flippedTiles[-1].text == self.flippedTiles[-2].text): #check last two elements
self.flippedTiles[-1].drawFaceDown()
self.flippedTiles[-2].drawFaceDown()
del self.flippedTiles[-2:]
if __name__ == '__main__':
c = Controller()
c.mainloop()
Goodluck :)
i have a page containing two tabs.i want to add a fadeIn effect when i change the tabs.Is that possible?
import sys
from PyQt4.QtCore import QTimeLine
from PyQt4.QtGui import *
class FaderWidget(QWidget):
def __init__(self, old_widget, new_widget):
QWidget.__init__(self, new_widget)
self.old_pixmap = QPixmap(new_widget.size())
old_widget.render(self.old_pixmap)
self.pixmap_opacity = 1.0
self.timeline = QTimeLine()
self.timeline.valueChanged.connect(self.animate)
self.timeline.finished.connect(self.close)
self.timeline.setDuration(333)
self.timeline.start()
self.resize(new_widget.size())
self.show()
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
painter.setOpacity(self.pixmap_opacity)
painter.drawPixmap(0, 0, self.old_pixmap)
painter.end()
def animate(self, value):
self.pixmap_opacity = 1.0 - value
self.repaint()
class StackedWidget(QStackedWidget):
def __init__(self, parent = None):
QStackedWidget.__init__(self, parent)
def setCurrentIndex(self, index):
self.fader_widget = FaderWidget(self.currentWidget(), self.widget(index))
QStackedWidget.setCurrentIndex(self, index)
def setPage1(self):
self.setCurrentIndex(0)
def setPage2(self):
self.setCurrentIndex(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = QWidget()
stack = StackedWidget()
stack.addWidget(QCalendarWidget())
editor = QTextEdit()
editor.setPlainText("Hello world! "*100)
stack.addWidget(editor)
page1Button = QPushButton("Page 1")
page2Button = QPushButton("Page 2")
page1Button.clicked.connect(stack.setPage1)
page2Button.clicked.connect(stack.setPage2)
layout = QGridLayout(window)
layout.addWidget(stack, 0, 0, 1, 2)
layout.addWidget(page1Button, 1, 0)
layout.addWidget(page2Button, 1, 1)
window.show()
sys.exit(app.exec_())
this is code that shows some fade effect but i m getting nothing from it and how it works and how to implement on tabs. it will be really appreciable if someone could help me implement it on tabs as well.
thanks in advance.
With the same logic as the code you show, each widget will be placed inside a QStackedWidget, where one of them will be the widget that will be displayed and the other will be the FaderWidget.
class FaderWidget(QWidget):
def __init__(self, *args, **kwargs):
QWidget.__init__(self, *args, **kwargs)
self.pixmap_opacity = None
self.timeline = QTimeLine(333, self)
self.timeline.valueChanged.connect(self.animate)
self.timeline.finished.connect(self.close)
def start(self, old_widget, new_widget):
self.pixmap_opacity = 1.0
self.old_pixmap = QPixmap(new_widget.size())
old_widget.render(self.old_pixmap)
self.timeline.start()
self.resize(new_widget.size())
self.show()
def paintEvent(self, event):
if self.pixmap_opacity:
QWidget.paintEvent(self, event)
painter = QPainter(self)
painter.setOpacity(self.pixmap_opacity)
painter.drawPixmap(0, 0, self.old_pixmap)
def animate(self, value):
self.pixmap_opacity = 1.0 - value
self.update()
class FaderTabWidget(QTabWidget):
def __init__(self, parent=None):
QTabWidget.__init__(self, parent)
self.currentChanged.connect(self.onCurrentIndex)
self.last = -1
self.current = self.currentIndex()
def onCurrentIndex(self, index):
self.last = self.current
self.current = self.currentIndex()
if self.widget(self.last):
self.widget(self.last).setCurrentIndex(1)
old_widget = self.widget(self.last).widget(0)
current_widget = self.widget(self.current).widget(0)
fade = self.widget(self.current).widget(1)
fade.start(old_widget, current_widget)
def addTab(self, widget, text):
stack = QStackedWidget(self)
stack.addWidget(widget)
fade = FaderWidget(self)
fade.timeline.finished.connect(lambda: stack.setCurrentIndex(0))
stack.addWidget(fade)
stack.setCurrentIndex(0 if self.currentIndex() == -1 else 1)
QTabWidget.addTab(self, stack, text)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = QWidget()
tabWidget = FaderTabWidget()
tabWidget.addTab(QCalendarWidget(), "Tab1")
editor = QTextEdit()
editor.setPlainText("Hello world! " * 100)
tabWidget.addTab(editor, "Tab2")
layout = QVBoxLayout(window)
layout.addWidget(tabWidget)
window.show()
sys.exit(app.exec_())
I want to change an image with my mouse. So, everytime I click somewhere, the image should change. I can show an image only one time. So I need to separate the initialization of everything that is needed to show an image from the part of code that is responsable for building an image.
Here is what I have got by far
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import pyqtSlot
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.gx=1
self.gy=1
self.tlb=QLabel()
self.lbl=QLabel()
self.image = QImage(512, 512, QImage.Format_RGB32)
self.hbox = QHBoxLayout()
self.pixmap = QPixmap()
self.initUI()
def mousePressEvent(self, QMouseEvent):
px = QMouseEvent.pos().x()
py = QMouseEvent.pos().y()
size = self.frameSize()
self.gx = px-size.width()/2
self.gy = py-size.height()/2
self.fillImage()
def initUI(self):
self.hbox = QHBoxLayout(self)
self.pixmap = QPixmap()
size = self.frameSize()
self.fillImage()
self.lbl = QLabel(self)
self.lbl.setPixmap(self.pixmap)
self.hbox.addWidget(self.lbl)
self.setLayout(self.hbox)
self.move(300, 200)
self.setWindowTitle('Red Rock')
self.tlb = QLabel(str(self.gx)+" : "+str(self.gy), self)
self.tlb.move(12,3)
self.show()
def fillImage(self):
for x in range(0, 512):
t = -1+(x/512)*2
color = (1 - (3 - 2*abs(t))*t**2)
for y in range(0, 512):
t1 = -1+(y/512)*2
color1 = (1 - (3 - 2*abs(t1))*t1**2)
result = (255/2)+(color * color1 * (t*self.gx+t1*self.gy) )*(255/2)
self.image.setPixel(x, y, qRgb(result, result, result))
self.pixmap = self.pixmap.fromImage(self.image)
self.tlb = QLabel(str(self.gx)+" : "+str(self.gy), self)
print(self.gx)
self.update()
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The print(self.gx) shows me that self.gx is changed, but the image isn't changed at all.
What do I do wrong?
You will have to tell the GUI that it needs to refresh the image.
In QT it seems you will need to call the update() or repaint() methods of the widget.
I've added self.lbl.setPixmap(self.pixmap) into fillImage before self.repaint() and self.update() and now it works, then i changed a little the code and now it looks like this
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import pyqtSlot
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.gx=1
self.gy=1
self.lbl=QLabel()
self.tlb = None
self.image = QImage(512, 512, QImage.Format_RGB32)
self.hbox = QHBoxLayout()
self.pixmap = QPixmap()
self.length = 1
self.initUI()
def mousePressEvent(self, QMouseEvent):
px = QMouseEvent.pos().x()
py = QMouseEvent.pos().y()
size = self.frameSize()
self.gx = px-size.width()/2
self.gy = py-size.height()/2
h = (self.gx**2+self.gy**2)**0.5
self.gx/=h
self.gy/=h
self.gx*=self.length
self.gy*=self.length
self.fillImage()
def wheelEvent(self,event):
self.length+=(event.delta()*0.001)
print(self.length)
def initUI(self):
self.hbox = QHBoxLayout(self)
self.pixmap = QPixmap()
self.move(300, 200)
self.setWindowTitle('Red Rock')
self.addedWidget = None
self.fillImage()
self.setLayout(self.hbox)
self.show()
def fillImage(self):
for x in range(0, 512):
t = -1+(x/512)*2
color = (1 - (3 - 2*abs(t))*t**2)
for y in range(0, 512):
t1 = -1+(y/512)*2
color1 = (1 - (3 - 2*abs(t1))*t1**2)
result = (255/2)+(color * color1 * (t*self.gx+t1*self.gy) )*(255/2)
self.image.setPixel(x, y, qRgb(result, result, result))
self.pixmap = self.pixmap.fromImage(self.image)
if self.lbl == None:
self.lbl = QLabel(self)
else:
self.lbl.setPixmap(self.pixmap)
if self.addedWidget == None:
self.hbox.addWidget(self.lbl)
self.addedWidget = True
if self.tlb==None:
self.tlb = QLabel(str(self.gx)+" : "+str(self.gy), self)
self.tlb.move(12,3)
else:
self.tlb.setText(str(self.gx)+" : "+str(self.gy))
self.repaint()
self.update()
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm using Pyside to create an interactive subclassed QGraphicsView - containing some subclassed QGraphicsItems.
It works well in its own module and receives mouse events.
But when used as a module from another file, and incorporated into another Layout - my mouse events are not being triggered.
However .itemChange is working.
Everything except the mouse events.
I am not using tracking events such as hover. I am using mousePressEvent and mouseReleaseEvent.
I have seen c++ responses about setting "setMouseTracking" but this is for widgets and my QGraphicsItems have been added as items not widgets. So when I call this funcion it tells me it doesn't exist for items. Also that seems to be for hover type of events - which I am not needing.
I believe I am subclassing properly and I pass on the events to the parent class. As I said at the start - my code works fine in a standalone file.
Any ideas what I've forgotten to do ?
Here is the standalone - working program:
Save as test_subclass_module.py
import sys
import weakref
import math
from PySide import QtCore, QtGui
###
class Edge(QtGui.QGraphicsItem):
Type = QtGui.QGraphicsItem.UserType + 2
def __init__(self, sourceNode, destNode):
QtGui.QGraphicsItem.__init__(self)
#
self.sourcePoint = QtCore.QPointF()
self.destPoint = QtCore.QPointF()
self.setAcceptedMouseButtons(QtCore.Qt.NoButton)
self.source = weakref.ref(sourceNode)
self.dest = weakref.ref(destNode)
self.source().addEdge(self)
self.dest().addEdge(self)
self.set_index()
self.adjust()
def type(self):
return Edge.Type
def sourceNode(self):
return self.source()
def setSourceNode(self, node):
self.source = weakref.ref(node)
self.adjust()
def destNode(self):
return self.dest()
def setDestNode(self, node):
self.dest = weakref.ref(node)
self.adjust()
def set_index(self):
self.setToolTip(self.source().label)
def adjust(self):
# do we have a line to draw ?
if self.source() and self.dest():
line = QtCore.QLineF(self.mapFromItem(self.source(), 0, 0), self.mapFromItem(self.dest(), 0, 0))
length = line.length()
if length > 20:
edgeOffset = QtCore.QPointF((line.dx() * 10) / length, (line.dy() * 10) / length)
self.prepareGeometryChange()
self.sourcePoint = line.p1() + edgeOffset
self.destPoint = line.p2() - edgeOffset
else: # want to make sure line not drawn
self.prepareGeometryChange()
self.sourcePoint = self.destPoint
def boundingRect(self):
# do we have a line to draw ?
if not self.source() or not self.dest():
return QtCore.QRectF()
else:
extra = 1
return QtCore.QRectF(self.sourcePoint,
QtCore.QSizeF(self.destPoint.x() - self.sourcePoint.x(),
self.destPoint.y() - self.sourcePoint.y())).normalized().adjusted(-extra, -extra, extra, extra)
def paint(self, painter, option, widget):
if self.source() and self.dest():
# Draw the line itself.
line = QtCore.QLineF(self.sourcePoint, self.destPoint)
if line.length() > 0.0:
painter.setPen(QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
painter.drawLine(line)
###
class Node(QtGui.QGraphicsItem):
Type = QtGui.QGraphicsItem.UserType + 1
def __init__(self, graphWidget, time, temp, pos):
QtGui.QGraphicsItem.__init__(self)
self.graph = weakref.ref(graphWidget)
self.edgeList = []
self.set_index(pos)
self.newPos = QtCore.QPointF()
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable)
self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges)
self.setCacheMode(self.DeviceCoordinateCache)
self.setZValue(-1)
#
self.temp = temp
self.time = time
x,y = self.map_temptime_to_pos()
self.setPos(x,y)
self.marker = False
def type(self):
return Node.Type
def addEdge(self, edge):
self.edgeList.append(weakref.ref(edge))
def set_index(self, index):
self.index = index
self.label = "Step %d" % index
self.setToolTip(self.label)
def get_prev_edge(self):
index = 1000
edge = False
for e in self.edgeList:
sn = e().source().index
dn = e().dest().index
if sn < index:
index = sn
edge = e
if dn < index:
index = dn
edge = e
return edge
def get_next_edge(self):
index = -1
edge = False
for e in self.edgeList:
sn = e().source().index
dn = e().dest().index
if sn > index:
index = sn
edge = e
if dn > index:
index = dn
edge = e
return edge
def map_temptime_to_pos(self):
x = self.time * self.graph().graph_width_ratio
y = self.graph().size[3] - self.temp * self.graph().graph_height_ratio
return (x,y)
def boundingRect(self):
adjust = 2.0
return QtCore.QRectF(-10 - adjust, -10 - adjust,
22 + adjust, 23 + adjust)
def paint(self, painter, option, widget):
painter.drawLine(QtCore.QLineF(6,-40,6,-2))
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(QtCore.Qt.lightGray)
painter.drawEllipse(-10, -10, 20, 20)
gradient = QtGui.QRadialGradient(0, 0, 22)
if option.state & QtGui.QStyle.State_Sunken: # selected
gradient.setColorAt(0, QtGui.QColor(QtCore.Qt.darkGreen).lighter(120))
else:
gradient.setColorAt(1, QtCore.Qt.blue)
painter.setBrush(QtGui.QBrush(gradient))
painter.setPen(QtGui.QPen(QtCore.Qt.black, 0))
painter.drawEllipse(-6, -6, 12, 12)
def itemChange(self, change, value):
if change == QtGui.QGraphicsItem.ItemPositionChange:
for edge in self.edgeList:
edge().adjust()
return QtGui.QGraphicsItem.itemChange(self, change, value)
def mousePressEvent(self, event):
if not self.graph().inhibit_edit:
self.update()
print "Node pressed"
QtGui.QGraphicsItem.mousePressEvent(self, event)
def mouseReleaseEvent(self, event):
if not self.graph().inhibit_edit:
self.update()
print "Node released"
#
QtGui.QGraphicsItem.mouseReleaseEvent(self, event)
###
class GraphWidget(QtGui.QGraphicsView):
def __init__(self):
QtGui.QGraphicsView.__init__(self)
self.size = (-30, 30, 600, 400)
#
scene = QtGui.QGraphicsScene(self)
scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
scene.setSceneRect(self.size[0],self.size[1],self.size[2],self.size[3])
self.setScene(scene)
self.setCacheMode(QtGui.QGraphicsView.CacheBackground)
self.setRenderHint(QtGui.QPainter.Antialiasing)
self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
#
self.maxtemp = 300
self.maxtime = 160
self.nodecount = 0
self.calc_upper_limits()
#
self.scale(0.8, 0.8)
self.setMinimumSize(600, 400)
self.setWindowTitle(self.tr("Elastic Nodes"))
self.inhibit_edit = False
def calc_upper_limits(self):
self.toptemp = (self.maxtemp / 100 + 1) * 100
self.toptime = (int(self.maxtime) / 30 + 1) * 30
self.graph_width_ratio = float(self.size[2]) /self.toptime
self.graph_height_ratio = float(self.size[3]) / self.toptemp
def add_node(self, time, temp, marker=False, pos=-1):
self.nodecount += 1
scene = self.scene()
# Insert Node into scene
node = Node(self, time, temp, self.nodecount)
scene.addItem(node)
# Insert new edges
nodes = self.get_ordered_nodes()
if len(nodes) > 1:
e = Edge(nodes[-2], node)
scene.addItem(e)
# cleanup edge tooltips
for n in self.get_ordered_nodes():
edges = n.edgeList
for e in edges:
e().set_index()
def get_ordered_nodes(self):
nodes = [item for item in self.scene().items() if isinstance(item, Node)]
nodes.sort(key=lambda n: n.index)
return nodes
def keyPressEvent(self, event):
key = event.key()
if key == QtCore.Qt.Key_Plus:
self.scaleView(1.2)
elif key == QtCore.Qt.Key_Minus:
self.scaleView(1 / 1.2)
else:
QtGui.QGraphicsView.keyPressEvent(self, event)
def mousePressEvent(self, event):
print "GraphWidget mouse"
QtGui.QGraphicsView.mousePressEvent(self, event)
def wheelEvent(self, event):
self.scaleView(math.pow(2.0, -event.delta() / 240.0))
def scaleView(self, scaleFactor):
factor = self.matrix().scale(scaleFactor, scaleFactor).mapRect(QtCore.QRectF(0, 0, 1, 1)).width()
if factor < 0.07 or factor > 100:
return
self.scale(scaleFactor, scaleFactor)
def drawBackground(self, painter, rect):
sceneRect = self.sceneRect()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
widget = GraphWidget()
widget.add_node(0, 25)
widget.add_node(30, 100)
widget.add_node(60, 200)
widget.show()
sys.exit(app.exec_())
Here is the parent program - which does not get the mouse events:
Called test_toplevel.py
# import user interface etc
from PySide import QtCore, QtGui
from test_tabs_ui import Ui_Form
from test_subclass_module import *
import sys
Programs = {"Gen13": {"steps": [[0, 0, 0], [0, 30, 30], [0, 60, 60], [0, 77, 77]]
}}
###-----------------------------------------------------------
### The dialog
class Nusku_tab_Add_kiln(QtGui.QWidget):
""" Create dialog to add/delete kilns from controlled kilns """
def __init__(self, parent=None):
# Get the UI loaded
super(Nusku_tab_Add_kiln, self).__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.current = Programs['Gen13']
# draw program in graphicsView
# swap out the standin
self.ui.graphLayout.removeWidget(self.ui.graphicsView)
self.ui.graphicsView.setParent(None)
self.ui.graphicsView.deleteLater()
self.graph = GraphWidget()
self.ui.graphLayout.addWidget(self.graph)
self.draw_graph()
def choose_program(self):
pass
def draw_graph(self):
graph = self.graph
graph.inhibit_edit = True
steps = self.current['steps']
for s in steps:
print s
graph.add_node(s[1],s[2])
###------------------------------------------------
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
prog = Nusku_tab_Add_kiln()
prog.show()
sys.exit(app.exec_())
For sake of completeness. Here is the ui file it imports:
test_tabs_ui.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'test_tabs.ui'
#
# Created: Wed Dec 05 15:20:02 2012
# by: pyside-uic 0.2.14 running on PySide 1.1.1
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(595, 540)
self.verticalLayout = QtGui.QVBoxLayout(Form)
self.verticalLayout.setObjectName("verticalLayout")
self.tabWidget = QtGui.QTabWidget(Form)
self.tabWidget.setObjectName("tabWidget")
self.Tab_Program = QtGui.QWidget()
self.Tab_Program.setObjectName("Tab_Program")
self.verticalLayout_2 = QtGui.QVBoxLayout(self.Tab_Program)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.frame_graph_status = QtGui.QFrame(self.Tab_Program)
self.frame_graph_status.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame_graph_status.setFrameShadow(QtGui.QFrame.Raised)
self.frame_graph_status.setObjectName("frame_graph_status")
self.horizontalLayout_7 = QtGui.QHBoxLayout(self.frame_graph_status)
self.horizontalLayout_7.setSpacing(0)
self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.frame_program = QtGui.QFrame(self.frame_graph_status)
self.frame_program.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame_program.setFrameShadow(QtGui.QFrame.Raised)
self.frame_program.setObjectName("frame_program")
self.graphLayout = QtGui.QVBoxLayout(self.frame_program)
self.graphLayout.setContentsMargins(-1, 0, -1, 0)
self.graphLayout.setObjectName("graphLayout")
self.graphicsView = QtGui.QGraphicsView(self.frame_program)
self.graphicsView.setObjectName("graphicsView")
self.graphLayout.addWidget(self.graphicsView)
self.horizontalLayout_7.addWidget(self.frame_program)
self.verticalLayout_2.addWidget(self.frame_graph_status)
self.widget_prog = QtGui.QWidget(self.Tab_Program)
self.widget_prog.setObjectName("widget_prog")
self.prog_layout = QtGui.QGridLayout(self.widget_prog)
self.prog_layout.setContentsMargins(4, 4, 4, 4)
self.prog_layout.setSpacing(0)
self.prog_layout.setContentsMargins(0, 0, 0, 0)
self.prog_layout.setObjectName("prog_layout")
self.verticalLayout_2.addWidget(self.widget_prog)
self.tabWidget.addTab(self.Tab_Program, "")
self.Tab_alarms = QtGui.QWidget()
self.Tab_alarms.setObjectName("Tab_alarms")
self.alarms_tab_layout = QtGui.QVBoxLayout(self.Tab_alarms)
self.alarms_tab_layout.setObjectName("alarms_tab_layout")
self.tabWidget.addTab(self.Tab_alarms, "")
self.Tab_settings = QtGui.QWidget()
self.Tab_settings.setObjectName("Tab_settings")
self.settings_tab_layout = QtGui.QVBoxLayout(self.Tab_settings)
self.settings_tab_layout.setObjectName("settings_tab_layout")
self.tabWidget.addTab(self.Tab_settings, "")
self.Tab_pid = QtGui.QWidget()
self.Tab_pid.setObjectName("Tab_pid")
self.verticalLayout_8 = QtGui.QVBoxLayout(self.Tab_pid)
self.verticalLayout_8.setSpacing(0)
self.verticalLayout_8.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_8.setObjectName("verticalLayout_8")
self.scrollArea_2 = QtGui.QScrollArea(self.Tab_pid)
self.scrollArea_2.setWidgetResizable(True)
self.scrollArea_2.setObjectName("scrollArea_2")
self.scrollAreaWidgetContents_2 = QtGui.QWidget()
self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 569, 494))
self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2")
self.PID_tab_layout = QtGui.QVBoxLayout(self.scrollAreaWidgetContents_2)
self.PID_tab_layout.setSpacing(0)
self.PID_tab_layout.setContentsMargins(0, 0, 0, 0)
self.PID_tab_layout.setObjectName("PID_tab_layout")
self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2)
self.verticalLayout_8.addWidget(self.scrollArea_2)
self.tabWidget.addTab(self.Tab_pid, "")
self.verticalLayout.addWidget(self.tabWidget)
self.retranslateUi(Form)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(Form)
Form.setTabOrder(self.tabWidget, self.graphicsView)
Form.setTabOrder(self.graphicsView, self.scrollArea_2)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.graphicsView.setToolTip(QtGui.QApplication.translate("Form", "decimal point", None, QtGui.QApplication.UnicodeUTF8))
self.graphicsView.setStatusTip(QtGui.QApplication.translate("Form", "Accuracy can be increased at lower temperatures", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Tab_Program), QtGui.QApplication.translate("Form", "Program", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Tab_alarms), QtGui.QApplication.translate("Form", "Alarms", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Tab_settings), QtGui.QApplication.translate("Form", "Settings", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Tab_pid), QtGui.QApplication.translate("Form", "PID", None, QtGui.QApplication.UnicodeUTF8))
because there is an answer - which reasonably asks me to delete my answer - I have to answer the question with my own answer to close it. After waiting 3 days... hopefully I can delete it - but probably not as it has an answer..
I downloaded and tried your application and saw it more or less working
(although the cursor position gets wrong in test_toplevel.py).
After removing graph.inhibit_edit = False also the cursor stays right.
So is the problem already solved? Then it would be very helpful to remove your
question or mak it as resolved. Or please clarify the question.