class QtImg(QtWidgets.QWidget): def __init__(self): super(self.__class__, self).__init__() self.bookId = "" self.epsId = 0 self.curIndex = 0 self.gridLayout = QtWidgets.QGridLayout(self) self.setWindowTitle("图片查看") self.setWindowModality(QtCore.Qt.ApplicationModal) self.resize(402, 509) # self.setWindowFlags(Qt.FramelessWindowHint) self.graphicsView = QtWidgets.QGraphicsView(self) self.graphicsView.setFrameStyle(QFrame.NoFrame) self.graphicsView.setObjectName("graphicsView") self.graphicsView.setBackgroundBrush(QColor(Qt.white)) self.graphicsView.setCursor(Qt.OpenHandCursor) self.graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.SmoothPixmapTransform) self.graphicsView.setCacheMode(self.graphicsView.CacheBackground) self.graphicsView.setViewportUpdateMode( self.graphicsView.SmartViewportUpdate) self.graphicsItem = QGraphicsPixmapItem() self.graphicsItem.setFlags(QGraphicsPixmapItem.ItemIsFocusable | QGraphicsPixmapItem.ItemIsMovable) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.CopyPicture) self.graphicsScene = QGraphicsScene(self) # 场景 self.graphicsView.setScene(self.graphicsScene) self.graphicsScene.addItem(self.graphicsItem) self.graphicsView.setMinimumSize(10, 10) self.pixMap = QPixmap("加载中") self.graphicsItem.setPixmap(self.pixMap) # self.radioButton.setChecked(True) self.isStripModel = False # self.radioButton.installEventFilter(self) # self.radioButton_2.installEventFilter(self) self.graphicsView.installEventFilter(self) self.graphicsView.setWindowFlag(Qt.FramelessWindowHint) self.gridLayout.addWidget(self.graphicsView) self._delta = 0.1 self.scaleCnt = 0 def ShowImg(self, pixMap): self.scaleCnt = 0 self.pixMap = QPixmap(pixMap) self.show() self.graphicsItem.setPixmap(self.pixMap) self.graphicsView.setSceneRect( QRectF(QPointF(0, 0), QPointF(self.pixMap.width(), self.pixMap.height()))) self.ScalePicture() def ScalePicture(self): rect = QRectF(self.graphicsItem.pos(), QSizeF(self.pixMap.size())) unity = self.graphicsView.transform().mapRect(QRectF(0, 0, 1, 1)) width = unity.width() height = unity.height() if width <= 0 or height <= 0: return self.graphicsView.scale(1 / width, 1 / height) viewRect = self.graphicsView.viewport().rect() sceneRect = self.graphicsView.transform().mapRect(rect) if sceneRect.width() <= 0 or sceneRect.height() <= 0: return x_ratio = viewRect.width() / sceneRect.width() y_ratio = viewRect.height() / sceneRect.height() x_ratio = y_ratio = min(x_ratio, y_ratio) self.graphicsView.scale(x_ratio, y_ratio) # if self.readImg.isStripModel: # height2 = self.pixMap.size().height() / 2 # height3 = self.graphicsView.size().height()/2 # height3 = height3/x_ratio # p = self.graphicsItem.pos() # self.graphicsItem.setPos(p.x(), p.y()+height2-height3) self.graphicsView.centerOn(rect.center()) for _ in range(abs(self.scaleCnt)): if self.scaleCnt > 0: self.graphicsView.scale(1.1, 1.1) else: self.graphicsView.scale(1 / 1.1, 1 / 1.1) def resizeEvent(self, event) -> None: super(self.__class__, self).resizeEvent(event) self.ScalePicture() def eventFilter(self, obj, ev): if ev.type() == QEvent.KeyPress: return True else: return super(self.__class__, self).eventFilter(obj, ev) def wheelEvent(self, event): if event.angleDelta().y() > 0: self.zoomIn() else: self.zoomOut() def zoomIn(self): """放大""" self.zoom(1.1) def zoomOut(self): """缩小""" self.zoom(1 / 1.1) def zoom(self, factor): """缩放 :param factor: 缩放的比例因子 """ _factor = self.graphicsView.transform().scale(factor, factor).mapRect( QRectF(0, 0, 1, 1)).width() if _factor < 0.07 or _factor > 100: # 防止过大过小 return if factor >= 1: self.scaleCnt += 1 else: self.scaleCnt -= 1 self.graphicsView.scale(factor, factor) def CopyPicture(self): clipboard = QApplication.clipboard() clipboard.setPixmap(self.pixMap) QtBubbleLabel.ShowMsgEx(self, "复制成功") return
class QtImg(QtWidgets.QWidget, Ui_Img): def __init__(self): super(self.__class__, self).__init__() Ui_Img.__init__(self) self.setupUi(self) self.bookId = "" self.epsId = 0 self.curIndex = 0 self.setWindowTitle("图片查看") self.setWindowModality(QtCore.Qt.ApplicationModal) self.resize(800, 900) self.radioButton.setChecked(True) self.index = 1 self.comboBox.setCurrentIndex(self.index) # self.setWindowFlags(Qt.FramelessWindowHint) self.graphicsView.setFrameStyle(QFrame.NoFrame) self.graphicsView.setObjectName("graphicsView") self.graphicsView.setBackgroundBrush(QColor(Qt.white)) self.graphicsView.setCursor(Qt.OpenHandCursor) self.graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.SmoothPixmapTransform) self.graphicsView.setCacheMode(self.graphicsView.CacheBackground) self.graphicsView.setViewportUpdateMode(self.graphicsView.SmartViewportUpdate) self.graphicsItem = QGraphicsPixmapItem() self.graphicsItem.setFlags(QGraphicsPixmapItem.ItemIsFocusable | QGraphicsPixmapItem.ItemIsMovable) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.CopyPicture) self.graphicsScene = QGraphicsScene(self) # 场景 self.graphicsView.setScene(self.graphicsScene) self.graphicsScene.addItem(self.graphicsItem) self.graphicsView.setMinimumSize(10, 10) self.pixMap = QPixmap("加载中") self.graphicsItem.setPixmap(self.pixMap) # self.radioButton.setChecked(True) self.isStripModel = False # self.radioButton.installEventFilter(self) # self.radioButton_2.installEventFilter(self) self.graphicsView.installEventFilter(self) self.graphicsView.setWindowFlag(Qt.FramelessWindowHint) self._delta = 0.1 self.scaleCnt = 0 def ShowImg(self, data): self.scaleCnt = 0 self.pixMap = QPixmap() self.pixMap.loadFromData(data) self.show() self.graphicsItem.setPixmap(self.pixMap) self.graphicsView.setSceneRect(QRectF(QPointF(0, 0), QPointF(self.pixMap.width(), self.pixMap.height()))) self.ScalePicture() def ScalePicture(self): rect = QRectF(self.graphicsItem.pos(), QSizeF( self.pixMap.size())) unity = self.graphicsView.transform().mapRect(QRectF(0, 0, 1, 1)) width = unity.width() height = unity.height() if width <= 0 or height <= 0: return self.graphicsView.scale(1 / width, 1 / height) viewRect = self.graphicsView.viewport().rect() sceneRect = self.graphicsView.transform().mapRect(rect) if sceneRect.width() <= 0 or sceneRect.height() <= 0: return x_ratio = viewRect.width() / sceneRect.width() y_ratio = viewRect.height() / sceneRect.height() x_ratio = y_ratio = min(x_ratio, y_ratio) self.graphicsView.scale(x_ratio, y_ratio) # if self.readImg.isStripModel: # height2 = self.pixMap.size().height() / 2 # height3 = self.graphicsView.size().height()/2 # height3 = height3/x_ratio # p = self.graphicsItem.pos() # self.graphicsItem.setPos(p.x(), p.y()+height2-height3) self.graphicsView.centerOn(rect.center()) for _ in range(abs(self.scaleCnt)): if self.scaleCnt > 0: self.graphicsView.scale(1.1, 1.1) else: self.graphicsView.scale(1/1.1, 1/1.1) def resizeEvent(self, event) -> None: super(self.__class__, self).resizeEvent(event) self.ScalePicture() def eventFilter(self, obj, ev): if ev.type() == QEvent.KeyPress: return True else: return super(self.__class__, self).eventFilter(obj, ev) def wheelEvent(self, event): if event.angleDelta().y() > 0: self.zoomIn() else: self.zoomOut() def zoomIn(self): """放大""" self.zoom(1.1) def zoomOut(self): """缩小""" self.zoom(1/1.1) def zoom(self, factor): """缩放 :param factor: 缩放的比例因子 """ _factor = self.graphicsView.transform().scale( factor, factor).mapRect(QRectF(0, 0, 1, 1)).width() if _factor < 0.07 or _factor > 100: # 防止过大过小 return if factor >= 1: self.scaleCnt += 1 else: self.scaleCnt -= 1 self.graphicsView.scale(factor, factor) def CopyPicture(self): clipboard = QApplication.clipboard() clipboard.setPixmap(self.pixMap) QtBubbleLabel.ShowMsgEx(self, "复制成功") return def ReduceScalePic(self): self.zoom(1/1.1) return def AddScalePic(self): self.zoom(1.1) return def OpenPicture(self): try: filename = QFileDialog.getOpenFileName(self, "Open Image", ".", "Image Files(*.jpg *.png)") if filename and len(filename) >= 1: name = filename[0] if os.path.isfile(name): f = open(name, "rb") data = f.read() f.close() QtImgMgr().ShowImg(data) except Exception as ex: Log.Error(ex) return def StartWaifu2x(self): if not QtImgMgr().data: return self.comboBox.setEnabled(False) self.changeButton.setEnabled(False) self.index = self.comboBox.currentIndex() index = self.comboBox.currentIndex() model = ToolUtil.GetModelByIndex(index) QtTask().AddConvertTask("", QtImgMgr().data, model, self.AddConvertBack, cleanFlag="QtImg") self.changeButton.setText("正在转换") return def AddConvertBack(self, data, waifuId, backParam, tick): if data: QtImgMgr().waifu2xData = data if self.radioButton.isChecked(): self.ShowImg(data) self.changeButton.setText("已转换") self.changeButton.setEnabled(False) else: self.changeButton.setEnabled(True) self.comboBox.setEnabled(True) return def SavePicture(self): data = QtImgMgr().waifu2xData if QtImgMgr().waifu2xData else QtImgMgr().data if not data: return try: today = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time())) filepath = QFileDialog.getSaveFileName(self, "保存", "{}.jpg".format(today)) if filepath and len(filepath) >= 1: name = filepath[0] f = open(name, "wb") f.write(data) f.close() except Exception as es: Log.Error(es) return def SwithPicture(self): if self.radioButton.isChecked() and QtImgMgr().waifu2xData: self.ShowImg(QtImgMgr().waifu2xData) else: self.ShowImg(QtImgMgr().data) return def ChangeModel(self, index): if self.comboBox.currentIndex() == self.index: return # self.index = self.comboBox.currentIndex() self.changeButton.setText("转换") self.changeButton.setEnabled(True) return
class NodeItem(AbstractNodeItem): """ Base Node item. Args: name (str): name displayed on the node. parent (QtWidgets.QGraphicsItem): parent item. """ def __init__(self, name='node', parent=None): super(NodeItem, self).__init__(name, parent) pixmap = QtGui.QPixmap(ICON_NODE_BASE) if pixmap.size().height() > NODE_ICON_SIZE: pixmap = pixmap.scaledToHeight(NODE_ICON_SIZE, QtCore.Qt.SmoothTransformation) self._properties['icon'] = ICON_NODE_BASE self._icon_item = QGraphicsPixmapItem(pixmap, self) self._icon_item.setTransformationMode(QtCore.Qt.SmoothTransformation) self._text_item = QGraphicsTextItem(self.name, self) self._x_item = XDisabledItem(self, 'DISABLED') self._input_items = {} self._output_items = {} self._widgets = {} def paint(self, painter, option, widget): """ Draws the node base not the ports. Args: painter (QtGui.QPainter): painter used for drawing the item. option (QtGui.QStyleOptionGraphicsItem): used to describe the parameters needed to draw. widget (QtWidgets.QWidget): not used. """ painter.save() bg_border = 1.0 rect = QtCore.QRectF(0.5 - (bg_border / 2), 0.5 - (bg_border / 2), self._width + bg_border, self._height + bg_border) radius = 2 border_color = QtGui.QColor(*self.border_color) path = QtGui.QPainterPath() path.addRoundedRect(rect, radius, radius) painter.setPen(QtGui.QPen(border_color.darker(200), 1.5)) painter.drawPath(path) rect = self.boundingRect() bg_color = QtGui.QColor(*self.color) painter.setBrush(bg_color) painter.setPen(QtCore.Qt.NoPen) painter.drawRoundRect(rect, radius, radius) if self.selected and NODE_SEL_COLOR: painter.setBrush(QtGui.QColor(*NODE_SEL_COLOR)) painter.drawRoundRect(rect, radius, radius) label_rect = QtCore.QRectF(rect.left() + (radius / 2), rect.top() + (radius / 2), self._width - (radius / 1.25), 28) path = QtGui.QPainterPath() path.addRoundedRect(label_rect, radius / 1.5, radius / 1.5) painter.setBrush(QtGui.QColor(0, 0, 0, 50)) painter.fillPath(path, painter.brush()) border_width = 0.8 if self.selected and NODE_SEL_BORDER_COLOR: border_width = 1.2 border_color = QtGui.QColor(*NODE_SEL_BORDER_COLOR) border_rect = QtCore.QRectF(rect.left() - (border_width / 2), rect.top() - (border_width / 2), rect.width() + border_width, rect.height() + border_width) pen = QtGui.QPen(border_color, border_width) pen.setCosmetic(self.viewer().get_zoom() < 0.0) path = QtGui.QPainterPath() path.addRoundedRect(border_rect, radius, radius) painter.setBrush(QtCore.Qt.NoBrush) painter.setPen(pen) painter.drawPath(path) painter.restore() def mousePressEvent(self, event): if event.button() == QtCore.Qt.MouseButton.LeftButton: start = PortItem().boundingRect().width() end = self.boundingRect().width() - start x_pos = event.pos().x() if not start <= x_pos <= end: event.ignore() super(NodeItem, self).mousePressEvent(event) def mouseReleaseEvent(self, event): if event.modifiers() == QtCore.Qt.AltModifier: event.ignore() return super(NodeItem, self).mouseReleaseEvent(event) def itemChange(self, change, value): if change == self.ItemSelectedChange and self.scene(): self.reset_pipes() if value: self.hightlight_pipes() self.setZValue(Z_VAL_NODE) if not self.selected: self.setZValue(Z_VAL_NODE + 1) return super(NodeItem, self).itemChange(change, value) def _tooltip_disable(self, state): tooltip = '<b>{}</b>'.format(self._properties['name']) if state: tooltip += ' <font color="red"><b>(DISABLED)</b></font>' tooltip += '<br/>{}<br/>'.format(self._properties['type']) self.setToolTip(tooltip) def _set_base_size(self): """ setup initial base size. """ self._width = NODE_WIDTH self._height = NODE_HEIGHT width, height = self.calc_size() if width > self._width: self._width = width if height > self._height: self._height = height def _set_text_color(self, color): """ set text color. Args: color (tuple): color value in (r, g, b, a). """ text_color = QtGui.QColor(*color) for port, text in self._input_items.items(): text.setDefaultTextColor(text_color) for port, text in self._output_items.items(): text.setDefaultTextColor(text_color) self._text_item.setDefaultTextColor(text_color) def activate_pipes(self): """ active pipe color. """ ports = self.inputs + self.outputs for port in ports: for pipe in port.connected_pipes: pipe.activate() def hightlight_pipes(self): """ highlight pipe color. """ ports = self.inputs + self.outputs for port in ports: for pipe in port.connected_pipes: pipe.highlight() def reset_pipes(self): """ reset the pipe color. """ ports = self.inputs + self.outputs for port in ports: for pipe in port.connected_pipes: pipe.reset() def calc_size(self): """ calculate minimum node size. """ width = 0.0 if self._widgets: widget_widths = [ w.boundingRect().width() for w in self._widgets.values() ] width = max(widget_widths) if self._text_item.boundingRect().width() > width: width = self._text_item.boundingRect().width() port_height = 0.0 if self._input_items: input_widths = [] for port, text in self._input_items.items(): input_width = port.boundingRect().width() * 2 if text.isVisible(): input_width += text.boundingRect().width() input_widths.append(input_width) width += max(input_widths) port = list(self._input_items.keys())[0] port_height = port.boundingRect().height() * 2 if self._output_items: output_widths = [] for port, text in self._output_items.items(): output_width = port.boundingRect().width() * 2 if text.isVisible(): output_width += text.boundingRect().width() output_widths.append(output_width) width += max(output_widths) port = list(self._output_items.keys())[0] port_height = port.boundingRect().height() * 2 in_count = len([p for p in self.inputs if p.isVisible()]) out_count = len([p for p in self.outputs if p.isVisible()]) height = port_height * (max([in_count, out_count]) + 2) if self._widgets: wid_height = sum( [w.boundingRect().height() for w in self._widgets.values()]) if wid_height > height: height = wid_height + (wid_height / len(self._widgets)) height += 10 return width, height def arrange_icon(self): """ Arrange node icon to the default top left of the node. """ self._icon_item.setPos(2.0, 2.0) def arrange_label(self): """ Arrange node label to the default top center of the node. """ text_rect = self._text_item.boundingRect() text_x = (self._width / 2) - (text_rect.width() / 2) self._text_item.setPos(text_x, 1.0) def arrange_widgets(self): """ Arrange node widgets to the default center of the node. """ if not self._widgets: return wid_heights = sum( [w.boundingRect().height() for w in self._widgets.values()]) pos_y = self._height / 2 pos_y -= wid_heights / 2 for name, widget in self._widgets.items(): rect = widget.boundingRect() pos_x = (self._width / 2) - (rect.width() / 2) widget.setPos(pos_x, pos_y) pos_y += rect.height() def arrange_ports(self, padding_x=0.0, padding_y=0.0): """ Arrange input, output ports in the node layout. Args: padding_x (float): horizontal padding. padding_y: (float): vertical padding. """ width = self._width - padding_x height = self._height - padding_y # adjust input position inputs = [p for p in self.inputs if p.isVisible()] if inputs: port_width = inputs[0].boundingRect().width() port_height = inputs[0].boundingRect().height() chunk = (height / len(inputs)) port_x = (port_width / 2) * -1 port_y = (chunk / 2) - (port_height / 2) for port in inputs: port.setPos(port_x + padding_x, port_y + (padding_y / 2)) port_y += chunk # adjust input text position for port, text in self._input_items.items(): if not port.isVisible(): continue txt_height = text.boundingRect().height() - 8.0 txt_x = port.x() + port.boundingRect().width() txt_y = port.y() - (txt_height / 2) text.setPos(txt_x + 3.0, txt_y) # adjust output position outputs = [p for p in self.outputs if p.isVisible()] if outputs: port_width = outputs[0].boundingRect().width() port_height = outputs[0].boundingRect().height() chunk = height / len(outputs) port_x = width - (port_width / 2) port_y = (chunk / 2) - (port_height / 2) for port in outputs: port.setPos(port_x, port_y + (padding_y / 2)) port_y += chunk # adjust output text position for port, text in self._output_items.items(): if not port.isVisible(): continue txt_width = text.boundingRect().width() txt_height = text.boundingRect().height() - 8.0 txt_x = width - txt_width - (port.boundingRect().width() / 2) txt_y = port.y() - (txt_height / 2) text.setPos(txt_x - 1.0, txt_y) def offset_icon(self, x=0.0, y=0.0): """ offset the icon in the node layout. Args: x (float): horizontal x offset y (float): vertical y offset """ if self._icon_item: icon_x = self._icon_item.pos().x() + x icon_y = self._icon_item.pos().y() + y self._icon_item.setPos(icon_x, icon_y) def offset_label(self, x=0.0, y=0.0): """ offset the label in the node layout. Args: x (float): horizontal x offset y (float): vertical y offset """ icon_x = self._text_item.pos().x() + x icon_y = self._text_item.pos().y() + y self._text_item.setPos(icon_x, icon_y) def offset_widgets(self, x=0.0, y=0.0): """ offset the node widgets in the node layout. Args: x (float): horizontal x offset y (float): vertical y offset """ for name, widget in self._widgets.items(): pos_x = widget.pos().x() pos_y = widget.pos().y() widget.setPos(pos_x + x, pos_y + y) def offset_ports(self, x=0.0, y=0.0): """ offset the ports in the node layout. Args: x (float): horizontal x offset y (float): vertical y offset """ for port, text in self._input_items.items(): port_x, port_y = port.pos().x(), port.pos().y() text_x, text_y = text.pos().x(), text.pos().y() port.setPos(port_x + x, port_y + y) text.setPos(text_x + x, text_y + y) for port, text in self._output_items.items(): port_x, port_y = port.pos().x(), port.pos().y() text_x, text_y = text.pos().x(), text.pos().y() port.setPos(port_x + x, port_y + y) text.setPos(text_x + x, text_y + y) def post_init(self, viewer=None, pos=None): """ Called after node has been added into the scene. Adjust the node layout and form after the node has been added. Args: viewer (NodeGraphQt.widgets.viewer.NodeViewer): not used pos (tuple): cursor position. """ # setup initial base size. self._set_base_size() # set text color when node is initialized. self._set_text_color(self.text_color) # set the tooltip self._tooltip_disable(self.disabled) # --- setup node layout --- # arrange label text self.arrange_label() self.offset_label(0.0, 5.0) # arrange icon self.arrange_icon() self.offset_icon(5.0, 2.0) # arrange node widgets self.arrange_widgets() self.offset_widgets(0.0, 10.0) # arrange input and output ports. self.arrange_ports(padding_y=35.0) self.offset_ports(0.0, 15.0) # set initial node position. if pos: self.xy_pos = pos @property def icon(self): return self._properties['icon'] @icon.setter def icon(self, path=None): self._properties['icon'] = path path = path or ICON_NODE_BASE pixmap = QtGui.QPixmap(path) if pixmap.size().height() > NODE_ICON_SIZE: pixmap = pixmap.scaledToHeight(NODE_ICON_SIZE, QtCore.Qt.SmoothTransformation) self._icon_item.setPixmap(pixmap) if self.scene(): self.post_init() @AbstractNodeItem.width.setter def width(self, width=0.0): w, h = self.calc_size() width = width if width > w else w AbstractNodeItem.width.fset(self, width) @AbstractNodeItem.height.setter def height(self, height=0.0): w, h = self.calc_size() h = 70 if h < 70 else h height = height if height > h else h AbstractNodeItem.height.fset(self, height) @AbstractNodeItem.disabled.setter def disabled(self, state=False): AbstractNodeItem.disabled.fset(self, state) for n, w in self._widgets.items(): w.widget.setDisabled(state) self._tooltip_disable(state) self._x_item.setVisible(state) @AbstractNodeItem.selected.setter def selected(self, selected=False): AbstractNodeItem.selected.fset(self, selected) if selected: self.hightlight_pipes() @AbstractNodeItem.name.setter def name(self, name=''): AbstractNodeItem.name.fset(self, name) self._text_item.setPlainText(name) if self.scene(): self.post_init() @property def inputs(self): """ Returns: list[PortItem]: input port graphic items. """ return list(self._input_items.keys()) @property def outputs(self): """ Returns: list[PortItem]: output port graphic items. """ return list(self._output_items.keys()) def add_input(self, name='input', multi_port=False, display_name=True): """ Args: name (str): name for the port. multi_port (bool): allow multiple connections. display_name (bool): display the port name. Returns: PortItem: input item widget """ port = PortItem(self) port.name = name port.port_type = IN_PORT port.multi_connection = multi_port port.display_name = display_name text = QGraphicsTextItem(port.name, self) text.font().setPointSize(8) text.setFont(text.font()) text.setVisible(display_name) self._input_items[port] = text if self.scene(): self.post_init() return port def add_output(self, name='output', multi_port=False, display_name=True): """ Args: name (str): name for the port. multi_port (bool): allow multiple connections. display_name (bool): display the port name. Returns: PortItem: output item widget """ port = PortItem(self) port.name = name port.port_type = OUT_PORT port.multi_connection = multi_port port.display_name = display_name text = QGraphicsTextItem(port.name, self) text.font().setPointSize(8) text.setFont(text.font()) text.setVisible(display_name) self._output_items[port] = text if self.scene(): self.post_init() return port def get_input_text_item(self, port_item): """ Args: port_item (PortItem): port item. Returns: QGraphicsTextItem: graphic item used for the port text. """ return self._input_items[port_item] def get_output_text_item(self, port_item): """ Args: port_item (PortItem): port item. Returns: QGraphicsTextItem: graphic item used for the port text. """ return self._output_items[port_item] @property def widgets(self): return dict(self._widgets) def add_combo_menu(self, name='', label='', items=None, tooltip=''): items = items or [] widget = NodeComboBox(self, name, label, items) widget.setToolTip(tooltip) self.add_widget(widget) return widget def add_text_input(self, name='', label='', text='', tooltip=''): widget = NodeLineEdit(self, name, label, text) widget.setToolTip(tooltip) self.add_widget(widget) return widget def add_checkbox(self, name='', label='', text='', state=False, tooltip=''): widget = NodeCheckBox(self, name, label, text, state) widget.setToolTip(tooltip) self.add_widget(widget) return widget def add_widget(self, widget): if isinstance(widget, NodeBaseWidget): self._widgets[widget.name] = widget else: raise TypeError('{} is not an instance of a node widget.') def get_widget(self, name): widget = self._widgets.get(name) if widget: return widget raise KeyError('node has no widget "{}"'.format(name)) def delete(self): for port, text in self._input_items.items(): port.delete() for port, text in self._output_items.items(): port.delete() super(NodeItem, self).delete() def from_dict(self, node_dict): super(NodeItem, self).from_dict(node_dict) widgets = node_dict.pop('widgets', {}) for name, value in widgets.items(): if self._widgets.get(name): self._widgets[name].value = value
class QtImgFrame(QFrame): def __init__(self, readImg): QFrame.__init__(self) self._readImg = weakref.ref(readImg) self.graphicsView = QtWidgets.QGraphicsView(self) self.graphicsView.setTransformationAnchor( self.graphicsView.AnchorUnderMouse) self.graphicsView.setResizeAnchor(self.graphicsView.AnchorUnderMouse) self.graphicsView.setFrameStyle(QFrame.NoFrame) self.graphicsView.setObjectName("graphicsView") self.qtTool = QtImgTool(self) self.graphicsView.setBackgroundBrush(QColor(Qt.white)) self.graphicsView.setCursor(Qt.OpenHandCursor) self.graphicsView.setResizeAnchor(self.graphicsView.AnchorViewCenter) self.graphicsView.setTransformationAnchor( self.graphicsView.AnchorViewCenter) self.graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.SmoothPixmapTransform) self.graphicsView.setCacheMode(self.graphicsView.CacheBackground) self.graphicsView.setViewportUpdateMode( self.graphicsView.SmartViewportUpdate) self.graphicsItem = QGraphicsPixmapItem() self.graphicsItem.setFlags(QGraphicsPixmapItem.ItemIsFocusable | QGraphicsPixmapItem.ItemIsMovable) self.graphicsScene = QGraphicsScene(self) # 场景 self.graphicsView.setScene(self.graphicsScene) self.graphicsScene.addItem(self.graphicsItem) self.graphicsView.setMinimumSize(10, 10) self.graphicsView.installEventFilter(self) self.graphicsView.setWindowFlag(Qt.FramelessWindowHint) self.pixMap = QPixmap() self.scaleCnt = 0 @property def readImg(self): return self._readImg() def resizeEvent(self, event) -> None: super(self.__class__, self).resizeEvent(event) self.ScaleFrame() self.ScalePicture() def ScaleFrame(self): size = self.size() w = size.width() h = size.height() self.graphicsView.setGeometry(0, 0, w, h) h = min(700, h) self.qtTool.setGeometry(w - 220, 0, 220, h) return def ScalePicture(self): if self.readImg.isStripModel: self.graphicsItem.setPos(0, 0) rect = QRectF(self.graphicsItem.pos(), QSizeF(self.pixMap.size())) unity = self.graphicsView.transform().mapRect(QRectF(0, 0, 1, 1)) width = unity.width() height = unity.height() if width <= 0 or height <= 0: return self.graphicsView.scale(1 / width, 1 / height) viewRect = self.graphicsView.viewport().rect() sceneRect = self.graphicsView.transform().mapRect(rect) if sceneRect.width() <= 0 or sceneRect.height() <= 0: return x_ratio = viewRect.width() / sceneRect.width() y_ratio = viewRect.height() / sceneRect.height() if not self.readImg.isStripModel: x_ratio = y_ratio = min(x_ratio, y_ratio) else: x_ratio = y_ratio = max(x_ratio, y_ratio) self.graphicsView.scale(x_ratio, y_ratio) if self.readImg.isStripModel: height2 = self.pixMap.size().height() / 2 height3 = self.graphicsView.size().height() / 2 height3 = height3 / x_ratio p = self.graphicsItem.pos() self.graphicsItem.setPos(p.x(), p.y() + height2 - height3) self.graphicsView.centerOn(rect.center()) for _ in range(abs(self.scaleCnt)): if self.scaleCnt > 0: self.graphicsView.scale(1.1, 1.1) else: self.graphicsView.scale(1 / 1.1, 1 / 1.1)