与PyQT5/PySide2相同的代码在MacOS上运行,但在Linux上引发错误



我使用PySide2、numpy和matplotlib编写了GUI,它在MacOS 11.2.3上运行时没有任何问题。然而,我在Ubuntu 20.4上运行代码时遇到了一个错误,该代码可以

我使用PySide2和matplotlib制作了一个GUI。目标是点击图像并将点击坐标存储在csv中。在Ubuntu上启动应用程序并点击";按钮";按钮,我收到一条错误消息(在代码后面提供(。似乎在Linux下,代码一直运行到第91行(尽管在图像上还没有点击,因此存储它们的数据帧显然是空的(,而在MacOS上,解释器已经在第76行停止等待用户的点击(在MacOS中,图片已经启动,终端上什么都没有(

这是代码:

import numpy as np 
import pandas as pd
import os
import sys 
import matplotlib.pyplot as plt

from PySide2 import QtGui
from PySide2 import QtCore
from PySide2.QtWidgets import QWidget, QApplication, QPushButton, QFileDialog
os.environ['QT_MAC_WANTS_LAYER'] = '1'

coords_Event = [] 
size_win_x = 10
size_win_y = 7
dpi_val = 100

class GUI(QWidget):
def __init__(self):
super(GUI, self).__init__()
self.initUI()
def initUI(self):
height_btn = 40 
width_btn = 350

button_position_x = 0
button_position_y = 20 

button_position_x = button_position_x + 50
btn2 = QPushButton('Button', self)     
btn2.clicked.connect(self.Event)
btn2.resize(width_btn, height_btn + 20)
btn2.move(button_position_y, button_position_x)       
self.show()

def Event(self):
dir_path = os.getcwd()
figure = plt.figure(figsize = (size_win_x,size_win_y), dpi=dpi_val) 
global coords_Event
coords_Event = []
def onclick(event):
ix, iy = event.xdata, event.ydata
print('x = %d, y = %d'%(
ix, iy))
global coords_Event
coords_Event.append((ix, iy))
return coords_Event        
cid = figure.canvas.mpl_connect('button_press_event', onclick)
pixel_array = np.array([[1,2,3], [100,5,6]])
figure2 = plt.imshow(pixel_array)
plt.savefig(dir_path + '/raw.png')
plt.title("the title")
plt.show()

print("ok1")
df = pd.DataFrame(coords_Event,
columns = ['X', 'Y']) 
string_csv = dir_path + "/coords_Event.csv"
print("ok2")
print(string_csv)
df.to_csv(string_csv, 
header=True)
df2 = pd.read_csv(string_csv)  
print("df2: ", df2)
print(df2.iloc[0]["X"])
print(df2.iloc[1]["X"])

print("ok3")
ic(coords_Event)
clicked_data = (coords_Event[1][0] - coords_Event[0][0]) 
df3 = pd.DataFrame ({"clicked_data": [clicked_data]})
string_csv = dir_path + "/clicked_data.csv"
print(string_csv)
df3.to_csv(string_csv, 
header=True)
print("ok5")
def main():
app = QApplication(sys.argv)
ex = GUI()
sys.exit(app.exec_())

if __name__ == '__main__':
main()

这是Ubuntu 上的错误消息

QCoreApplication::exec: The event loop is already running
ok1
[]
ok2
/home/user/Documents/myApp/coords_Event.csv
df2:  Empty DataFrame
Columns: [Unnamed: 0, X, Y]
Index: []
Traceback (most recent call last):
File "debug_05.py", line 92, in Event
print(df2.iloc[0]["X"])
File "/home/user/Documents/myApp/env/lib/python3.8/site-packages/pandas/core/indexing.py", line 895, in __getitem__
return self._getitem_axis(maybe_callable, axis=axis)
File "/home/user/Documents/myApp/env/lib/python3.8/site-packages/pandas/core/indexing.py", line 1501, in _getitem_axis
self._validate_integer(key, axis)
File "/home/user/Documents/myApp/env/lib/python3.8/site-packages/pandas/core/indexing.py", line 1444, in _validate_integer
raise IndexError("single positional indexer is out-of-bounds")
IndexError: single positional indexer is out-of-bounds

我检查了Ubuntu和MacOS上的环境包,它们完全是相同的

这是一段可能更为直接的代码,它在linux下输出点击的坐标,但在MacOS:下不输出

import numpy as np 
import pandas as pd
import os
import sys 
import matplotlib.pyplot as plt

from PySide2 import QtGui
from PySide2 import QtCore
from PySide2.QtWidgets import QWidget, QApplication, QPushButton, QFileDialog
os.environ['QT_MAC_WANTS_LAYER'] = '1'
coords_Event = [] 
size_win_x = 2
size_win_y = 2
dpi_val = 100
class GUI(QWidget):
def __init__(self):
super(GUI, self).__init__()
self.initUI()
def initUI(self):
height_btn = 40 
width_btn = 350

button_position_x = 0
button_position_y = 20 

button_position_x = button_position_x + 50
btn2 = QPushButton('Button', self)     
btn2.clicked.connect(self.Event)
btn2.resize(width_btn, height_btn + 20)
btn2.move(button_position_y, button_position_x)       
self.show()
def Event(self):
dir_path = os.getcwd()
def onclick(event):
global ix, iy
ix, iy = event.xdata, event.ydata
print('x = %d, y = %d'%(
ix, iy))
global coords_Event
coords_Event.append((ix, iy))
return coords_Event        
fig = plt.figure(figsize = (size_win_x,size_win_y), dpi=dpi_val) 
pixel_array = np.array([[1,2,3,4,5,6], [1,2,3,4,5,6], [1,2,3,4,5,6]])
fig2 = plt.imshow(pixel_array)

cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()
print(coords_Event)
def main():
app = QApplication(sys.argv)
ex = GUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

我在Windows上运行,您的代码也有同样的问题。

我注意到的第一件事是,您没有指定后端。在我的系统上,单击按钮只会显示一个没有GUI的图像。在这种情况下,没有可连接的点击事件,也没有可关闭的GUI窗口。

我假设在MacOS上会显示一个绘图图,让你点击该图几次。关闭图形后,将运行print("ok1")。如果是这种情况,plt.show()正在阻塞并等待窗口关闭。这实际上是一个matplotlib问题。我尝试运行plt.show(block=True),但它不适用于PySide2。可能存在PySide2兼容性问题,或者配置文件或系统设置导致了不同的行为。

下面的代码会检查figurate.canvas是否可见,并阻止它直到关闭。

import numpy as np
import pandas as pd
import os
import sys
from PySide2 import QtGui
from PySide2 import QtCore
from PySide2.QtWidgets import QWidget, QApplication, QPushButton, QFileDialog
os.environ['QT_MAC_WANTS_LAYER'] = '1'
import matplotlib
try:
matplotlib.rcParams['backend.qt5'] = 'PySide2'
except (KeyError, Exception):
pass
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt

coords_Event = []
size_win_x = 10
size_win_y = 7
dpi_val = 100

dir_path = os.getcwd()

class GUI(QWidget):
def __init__(self):
super(GUI, self).__init__()
self.initUI()
def initUI(self):
self.coords_Event = []
height_btn = 40
width_btn = 350
button_position_x = 0
button_position_y = 20
button_position_x = button_position_x + 50
btn2 = QPushButton('Button', self)
btn2.clicked.connect(self.Event)
btn2.resize(width_btn, height_btn + 20)
btn2.move(button_position_y, button_position_x)
self.show()
def save_coord(self, event):
ix, iy = event.xdata, event.ydata
print('x = %d, y = %d' % (ix, iy))
self.coords_Event.append((ix, iy))
return coords_Event
def Event(self):
figure = plt.figure(figsize=(size_win_x, size_win_y), dpi=dpi_val)
self.coords_Event = []
cid = figure.canvas.mpl_connect('button_press_event', self.save_coord)
pixel_array = np.array([[1, 2, 3], [100, 5, 6]])
figure2 = plt.imshow(pixel_array)
plt.savefig(dir_path + '/raw.png')
plt.title("the title")
# Block here until figure is closed.
plt.show()
while figure.canvas.isVisible():
QApplication.processEvents()
self.finish_coords()
def finish_coords(self):
print("ok1")
df = pd.DataFrame(self.coords_Event, columns = ['X', 'Y'])
string_csv = dir_path + "/coords_Event.csv"
print("ok2")
print(string_csv)
df.to_csv(string_csv, header=True)
df2 = pd.read_csv(string_csv)
print("df2: ", df2)
print(df2.iloc[0]["X"])
print(df2.iloc[1]["X"])
print("ok3")
# ic(coords_Event)
clicked_data = (self.coords_Event[1][0] - self.coords_Event[0][0])
df3 = pd.DataFrame({"clicked_data": [clicked_data]})
string_csv = dir_path + "/clicked_data.csv"
print(string_csv)
df3.to_csv(string_csv, header=True)
print("ok5")

def main():
app = QApplication(sys.argv)
ex = GUI()
sys.exit(app.exec_())

if __name__ == '__main__':
main()

相关内容

最新更新