PyQt5 GUI程序无法显示,报AttributeError: 'Img_controller'无'ui'属性
PyQt5 GUI程序报错AttributeError: 'Img_controller' object has no attribute 'ui'排查与修复
问题描述
基于PyQt5开发GUI程序,参考教程仅修改img_controller.py模块,初始化Img_controller实例时传入Qt Designer生成的Ui_MainWindow实例,由该模块修改UI属性。原教程程序运行正常,但我的程序无法显示主窗口,报错AttributeError: 'Img_controller' object has no attribute 'ui'。已在Img_controller的__init__方法中设置self.ui = ui,问题依旧,附上代码请求排查。
错误原因分析
- 核心问题:初始化顺序错误:
Img_controller的__init__方法中,先调用self.read_img(self.img_path),而read_img会触发set_img_ratio,进而调用__update_img等需要访问self.ui的方法,但此时self.ui = ui还未执行,导致属性未定义报错。 - 次要问题:
__update_text_img_shape方法中使用未定义的self.origin_width和self.origin_height,需替换为已定义的self.orig_w和self.orig_h。- 缩放逻辑混淆:
set_img_ratio会将滑块值转换为指数缩放比例,但set_zoom_in/set_zoom_out直接操作转换后的比例值,导致缩放逻辑混乱,需区分滑块原始值(0-100)和实际缩放比例。 read_img中计算bytesPerline时参数错误,应为图片宽度乘以通道数。
修复后的代码
修复后的img_controller.py
from PyQt5 import QtCore, QtGui import cv2 from UI import Ui_MainWindow class Img_controller(object): def __init__(self, ui:Ui_MainWindow, slider_value:int = 50): super(Img_controller, self).__init__() self.img_path = 'sad.jpg' self.slider_value = slider_value # 保存滑块原始值(0-100) self.ui = ui # 先赋值UI实例,再执行后续依赖UI的操作 self.read_img(self.img_path) def read_img(self,img_path): try: self.img = cv2.imread(img_path) self.orig_h, self.orig_w, self.orig_c = self.img.shape self.img_path = img_path except: self.img = cv2.imread(self.img_path) self.orig_h, self.orig_w, self.orig_c = self.img.shape # 修正bytesPerline计算:宽度*通道数 bytesPerline = self.orig_w * self.orig_c self.qimg = QtGui.QImage(self.img, self.orig_w, self.orig_h, bytesPerline, QtGui.QImage.Format_RGB888).rgbSwapped() self.origin_qpixmap = QtGui.QPixmap.fromImage(self.qimg) self.slider_value = 50 self.set_img_ratio() def set_img_ratio(self): # 根据滑块值计算缩放比例 self.img_ratio = pow(10, (self.slider_value - 50)/50) qpixmap_height = self.orig_h * self.img_ratio self.qpixmap = self.origin_qpixmap.scaledToHeight(qpixmap_height) # 更新UI界面 self.__update_img() self.__update_text_ratio() self.__update_text_img_shape() self.__update_text_file_path() def __update_img(self): self.ui.image_label.setPixmap(self.qpixmap) self.ui.image_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) def __update_text_file_path(self): self.ui.label_filename.setText(f"File path = {self.img_path}") def __update_text_ratio(self): self.ui.label_resolution.setText(f"{int(100*self.img_ratio)} %") def __update_text_img_shape(self): current_text = f"Current img shape = ({self.qpixmap.width()}, {self.qpixmap.height()})" origin_text = f"Origin img shape = ({self.orig_w}, {self.orig_h})" self.ui.label_img_shape.setText(current_text + "\t" + origin_text) def set_zoom_in(self): self.slider_value = max(0, self.slider_value - 1) self.ui.slider.setValue(self.slider_value) # 同步滑块UI值 self.set_img_ratio() def set_zoom_out(self): self.slider_value = min(100, self.slider_value + 1) self.ui.slider.setValue(self.slider_value) # 同步滑块UI值 self.set_img_ratio() def set_slider_value(self, value): self.slider_value = value self.set_img_ratio()
修复后的controller.py
from PyQt5 import QtCore,QtWidgets,QtGui from PyQt5.QtWidgets import QMainWindow,QFileDialog from img_controller import Img_controller from UI import Ui_MainWindow class Ui_controller(QMainWindow): def __init__(self): super(Ui_controller,self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setup_control() def setup_control(self): self.img_controller = Img_controller(ui = self.ui) self.ui.btn_open.clicked.connect(self.open_file) self.ui.btn_zoomin.clicked.connect(self.img_controller.set_zoom_in) self.ui.btn_zoomout.clicked.connect(self.img_controller.set_zoom_out) self.ui.slider.valueChanged.connect(self.getslidervalue) def open_file(self): filename, filetype = QFileDialog.getOpenFileName(self, "Open file", "./") if filename: # 增加判断,避免取消选择时报错 self.init_new_picture(filename) def init_new_picture(self, filename): self.ui.slider.setValue(50) # 使用标准setValue方法设置滑块值 self.img_controller.read_img(filename) def getslidervalue(self): self.img_controller.set_slider_value(self.ui.slider.value()) # 移除多余的+1操作
内容的提问来源于stack exchange,提问作者Johnson Lin
相关产品推荐
相关产品推荐

