def setLine(self, line): """ Set the arrow base line (a `QLineF` in object coordinates). """ if self.__line != line: self.__line = line # local item coordinate system geom = self.geometry().translated(-self.pos()) if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) arrow_shape = arrow_path_concave(line, self.lineWidth()) arrow_rect = arrow_shape.boundingRect() if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) if self.__autoAdjustGeometry: # Shrink the geometry if required. geom = geom.intersected(arrow_rect) # topLeft can move changing the local coordinates. diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) self.__arrowItem.setLine(line) self.__line = line # parent item coordinate system geom.translate(self.pos()) self.setGeometry(geom)
def draw_text(self, txt, txtlen, window): if ((txtlen>0) and not ((txt == self.cursor_char) and (self._cursor_visible == False))): # If there IS something to print if (self.pbuffer_painter[window.id] == None): self.brush.setColor(self.ztoq_color[self.cur_bg]) self.pbuffer_painter[window.id] = QPainter(self.pbuffer[window.id]) self.pbuffer_painter[window.id].setPen(self.ztoq_color[self.cur_fg]) self.pbuffer_painter[window.id].setBackground(self.brush) painter = self.pbuffer_painter[window.id] # @type window ZWindow if (window.cursor == None): if (window.id == 0): # Main window window.set_cursor_position(1, self.height) window.set_cursor_real_position(2, self.height*(self.linesize-1)) else: window.set_cursor_position(1, 1) window.set_cursor_real_position(2, self.linesize-1) if (txt=='\n'): if (window.cursor[1]==self.height): if (window.scrolling): self.scroll(painter) window.set_cursor_position(1, window.cursor[1]) window.set_cursor_real_position(2, window.cursor_real_pos[1]) else: window.set_cursor_position(1, window.cursor[1]+1) window.set_cursor_real_position(2, window.cursor_real_pos[1]+self.linesize) else: rect = QRectF(window.cursor_real_pos[0], window.cursor_real_pos[1], self.pbuffer[window.id].width()-window.cursor_real_pos[0], self.linesize) painter.setFont(self.font()) #painter.setRenderHint(QPainter.TextAntialiasing) if (self._input_buffer_printing == False): painter.setBackgroundMode(Qt.OpaqueMode) else: painter.setBackgroundMode(Qt.TransparentMode) bounding_rect = painter.boundingRect(rect,txt) if (rect.contains(bounding_rect)): #print rect.x(), rect.y(), rect.width(),rect.height(), txt, bounding_rect painter.drawText(bounding_rect, txt) if txt != self.cursor_char: window.set_cursor_position(window.cursor[0]+txtlen, window.cursor[1]) window.set_cursor_real_position(rect.x()+bounding_rect.width(), rect.y()) else: # There is not enough space #print "Not enough space to print:", txt self.scroll(painter) window.set_cursor_position(1, self.height) window.set_cursor_real_position(2, self.height*(self.linesize-1)) rect.setX(2) rect.setY(window.cursor_real_pos[1]) rect.setWidth(self.pbuffer[window.id].width()-window.cursor_real_pos[0]) rect.setHeight(self.linesize) bounding_rect = painter.boundingRect(rect,txt) painter.drawText(bounding_rect, txt) if txt != self.cursor_char: window.set_cursor_position(window.cursor[0]+txtlen, window.cursor[1]) window.set_cursor_real_position(rect.x()+bounding_rect.width(), rect.y())
def clean_input_buffer_from_screen(self): rect = QRectF() rect.setX(self.lastwindow.cursor_real_pos[0]) rect.setY(self.lastwindow.cursor_real_pos[1]) rect.setWidth(self.pbuffer[0].width()-self.lastwindow.cursor_real_pos[0]+1) rect.setHeight(self.linesize) txtbuffer = '' for w in self.input_buf: txtbuffer += w bounding_rect = self.pbuffer_painter[0].boundingRect(rect, txtbuffer) if (rect.contains(bounding_rect)): # string fits in this line self.pbuffer_painter[0].eraseRect(bounding_rect) #self.pbuffer_painter.drawRect(bounding_rect) #print 'Erasing rect', bounding_rect else: self.pbuffer_painter[0].eraseRect(rect)
class MainWindow(QWidget): def __init__(self): super(MainWindow, self).__init__() # na pozici [0, 0] se šířkou 50px a výškou 50px # musíme ho vykreslit my, protože je to pouze abstraktní objekt (abstrakní ve smyslu, že nám pouze uchovává data a poskytuje potřebné výpočty) self.__drag_and_drop_rect = QRectF(QPointF(), QSizeF(50, 50)) self.__rect_color = QColor("red") self.__mouse_pressed = False def paintEvent(self, _): """ :type _: QPaintEvent """ painter = QPainter(self) painter.setBrush(QBrush(self.__rect_color)) painter.setPen(QPen(self.__rect_color)) painter.drawRect(self.__drag_and_drop_rect) def mousePressEvent(self, mouse_event): """ :type mouse_event: QMouseEvent """ # je v bod kliknutí v obdelníku? self.__mouse_pressed = self.__drag_and_drop_rect.contains(mouse_event.pos()) def mouseReleaseEvent(self, _): """ :type _: QMouseEvent """ self.__mouse_pressed = False def mouseMoveEvent(self, mouse_event): """ :type mouse_event: QMouseEvent """ if not self.__mouse_pressed: return # přesuň obdelník na pozici kurzoru self.__drag_and_drop_rect.moveTo(mouse_event.pos()) # obnov okno(zavolá se metoda paintEvent) self.update()
def betweenTwoPoints(self, point, first, second): """ Checks whether 'point' lies between 'first' and 'second'. This function can currently (08-11-15) only deal with horizontal and vertical distances. """ halfthick = 0.5 * self.CONNECTION_THICKNESS * self.zoomFactor() direction = self.getPointToPointDirection(first, second) topLeft = QPointF() bottomRight = QPointF() if direction == self.ConnectionDirection.LEFT: # horizontal, negative topLeft.setX(second.x()) topLeft.setY(second.y() - halfthick) bottomRight.setX(first.x()) bottomRight.setY(first.y() + halfthick) elif direction == self.ConnectionDirection.RIGHT: # horizontal, positive topLeft.setX(first.x()) topLeft.setY(first.y() - halfthick) bottomRight.setX(second.x()) bottomRight.setY(second.y() + halfthick) elif direction == self.ConnectionDirection.UP: # vertical, negative topLeft.setX(second.x() - halfthick) topLeft.setY(second.y()) bottomRight.setX(first.x() + halfthick) bottomRight.setY(first.y()) elif direction == self.ConnectionDirection.UP: # vertical, positive topLeft.setX(first.x() - halfthick) topLeft.setY(first.y()) bottomRight.setX(second.x() + halfthick) bottomRight.setY(second.y()) else: return False rect = QRectF(topLeft, bottomRight) return rect.contains(QPointF(point))
def adjustGeometry(self): """ Adjust the widget geometry to exactly fit the arrow inside while preserving the arrow path scene geometry. """ # local system coordinate geom = self.geometry().translated(-self.pos()) line = self.__line arrow_rect = self.__arrowItem.shape().boundingRect() if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) geom = geom.intersected(arrow_rect) diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) geom.translate(self.pos()) self.setGeometry(geom) self.setLine(line)
class XYGraphicsScene(QGraphicsScene): def __init__(self, parent): QGraphicsScene.__init__(self, parent) self.cc_x = 1 self.cc_y = 2 self.m_channels = [] self.m_mouseLock = False self.m_smooth = False self.m_smooth_x = 0 self.m_smooth_y = 0 self.setBackgroundBrush(Qt.black) cursorPen = QPen(QColor(255, 255, 255), 2) cursorBrush = QColor(255, 255, 255, 50) self.m_cursor = self.addEllipse(QRectF(-10, -10, 20, 20), cursorPen, cursorBrush) linePen = QPen(QColor(200, 200, 200, 100), 1, Qt.DashLine) self.m_lineH = self.addLine(-9999, 0, 9999, 0, linePen) self.m_lineV = self.addLine(0, -9999, 0, 9999, linePen) self.p_size = QRectF(-100, -100, 100, 100) def setControlX(self, x): self.cc_x = x def setControlY(self, y): self.cc_y = y def setChannels(self, channels): self.m_channels = channels def setPosX(self, x, forward=True): if not self.m_mouseLock: pos_x = x * (self.p_size.x() + self.p_size.width()) self.m_cursor.setPos(pos_x, self.m_cursor.y()) self.m_lineV.setX(pos_x) if forward: self.sendMIDI(pos_x / (self.p_size.x() + self.p_size.width()), None) else: self.m_smooth_x = pos_x def setPosY(self, y, forward=True): if not self.m_mouseLock: pos_y = y * (self.p_size.y() + self.p_size.height()) self.m_cursor.setPos(self.m_cursor.x(), pos_y) self.m_lineH.setY(pos_y) if forward: self.sendMIDI(None, pos_y / (self.p_size.y() + self.p_size.height())) else: self.m_smooth_y = pos_y def setSmooth(self, smooth): self.m_smooth = smooth def setSmoothValues(self, x, y): self.m_smooth_x = x * (self.p_size.x() + self.p_size.width()) self.m_smooth_y = y * (self.p_size.y() + self.p_size.height()) def handleCC(self, param, value): sendUpdate = False xp = yp = 0.0 if param == self.cc_x: sendUpdate = True xp = (float(value) / 63) - 1.0 yp = self.m_cursor.y() / (self.p_size.y() + self.p_size.height()) if xp < -1.0: xp = -1.0 elif xp > 1.0: xp = 1.0 self.setPosX(xp, False) if param == self.cc_y: sendUpdate = True xp = self.m_cursor.x() / (self.p_size.x() + self.p_size.width()) yp = (float(value) / 63) - 1.0 if yp < -1.0: yp = -1.0 elif yp > 1.0: yp = 1.0 self.setPosY(yp, False) if sendUpdate: self.emit(SIGNAL("cursorMoved(double, double)"), xp, yp) def handleMousePos(self, pos): if not self.p_size.contains(pos): if pos.x() < self.p_size.x(): pos.setX(self.p_size.x()) elif pos.x() > self.p_size.x() + self.p_size.width(): pos.setX(self.p_size.x() + self.p_size.width()) if pos.y() < self.p_size.y(): pos.setY(self.p_size.y()) elif pos.y() > self.p_size.y() + self.p_size.height(): pos.setY(self.p_size.y() + self.p_size.height()) self.m_smooth_x = pos.x() self.m_smooth_y = pos.y() if not self.m_smooth: self.m_cursor.setPos(pos) self.m_lineH.setY(pos.y()) self.m_lineV.setX(pos.x()) xp = pos.x() / (self.p_size.x() + self.p_size.width()) yp = pos.y() / (self.p_size.y() + self.p_size.height()) self.sendMIDI(xp, yp) self.emit(SIGNAL("cursorMoved(double, double)"), xp, yp) def sendMIDI(self, xp=None, yp=None): global jack_midi_out_data rate = float(0xff) / 4 if xp != None: value = int((xp * rate) + rate) for channel in self.m_channels: jack_midi_out_data.put_nowait((0xB0 + channel - 1, self.cc_x, value)) if yp != None: value = int((yp * rate) + rate) for channel in self.m_channels: jack_midi_out_data.put_nowait((0xB0 + channel - 1, self.cc_y, value)) def updateSize(self, size): self.p_size.setRect(-(size.width() / 2), -(size.height() / 2), size.width(), size.height()) def updateSmooth(self): if self.m_smooth: if self.m_cursor.x() != self.m_smooth_x or self.m_cursor.y() != self.m_smooth_y: if abs(self.m_cursor.x() - self.m_smooth_x) <= 0.001: self.m_smooth_x = self.m_cursor.x() return elif abs(self.m_cursor.y() - self.m_smooth_y) <= 0.001: self.m_smooth_y = self.m_cursor.y() return new_x = (self.m_smooth_x + self.m_cursor.x() * 3) / 4 new_y = (self.m_smooth_y + self.m_cursor.y() * 3) / 4 pos = QPointF(new_x, new_y) self.m_cursor.setPos(pos) self.m_lineH.setY(pos.y()) self.m_lineV.setX(pos.x()) xp = pos.x() / (self.p_size.x() + self.p_size.width()) yp = pos.y() / (self.p_size.y() + self.p_size.height()) self.sendMIDI(xp, yp) self.emit(SIGNAL("cursorMoved(double, double)"), xp, yp) def keyPressEvent(self, event): event.accept() def wheelEvent(self, event): event.accept() def mousePressEvent(self, event): self.m_mouseLock = True self.handleMousePos(event.scenePos()) QGraphicsScene.mousePressEvent(self, event) def mouseMoveEvent(self, event): self.handleMousePos(event.scenePos()) QGraphicsScene.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): self.m_mouseLock = False QGraphicsScene.mouseReleaseEvent(self, event)
def update(self, zoom_only=False): self.update_ticks() line_color = self.plot.color(OWPalette.Axis) text_color = self.plot.color(OWPalette.Text) if not self.graph_line or not self.scene(): return self.line_item.setLine(self.graph_line) self.line_item.setPen(line_color) if self.title: self.title_item.setHtml('<b>' + self.title + '</b>') self.title_item.setDefaultTextColor(text_color) if self.title_location == AxisMiddle: title_p = 0.5 elif self.title_location == AxisEnd: title_p = 0.95 else: title_p = 0.05 title_pos = self.graph_line.pointAt(title_p) v = self.graph_line.normalVector().unitVector() dense_text = False if hasattr(self, 'title_margin'): offset = self.title_margin elif self._ticks: if self.should_be_expanded(): offset = 55 dense_text = True else: offset = 35 else: offset = 10 if self.title_above: title_pos = title_pos + (v.p2() - v.p1()) * ( offset + QFontMetrics(self.title_item.font()).height()) else: title_pos = title_pos - (v.p2() - v.p1()) * offset ## TODO: Move it according to self.label_pos self.title_item.setVisible(self.show_title) self.title_item.setRotation(-self.graph_line.angle()) c = self.title_item.mapToParent( self.title_item.boundingRect().center()) tl = self.title_item.mapToParent( self.title_item.boundingRect().topLeft()) self.title_item.setPos(title_pos - c + tl) ## Arrows if not zoom_only: if self.start_arrow_item: self.scene().removeItem(self.start_arrow_item) self.start_arrow_item = None if self.end_arrow_item: self.scene().removeItem(self.end_arrow_item) self.end_arrow_item = None if self.arrows & AxisStart: if not zoom_only or not self.start_arrow_item: self.start_arrow_item = QGraphicsPathItem( self.arrow_path, self) self.start_arrow_item.setPos(self.graph_line.p1()) self.start_arrow_item.setRotation(-self.graph_line.angle() + 180) self.start_arrow_item.setBrush(line_color) self.start_arrow_item.setPen(line_color) if self.arrows & AxisEnd: if not zoom_only or not self.end_arrow_item: self.end_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.end_arrow_item.setPos(self.graph_line.p2()) self.end_arrow_item.setRotation(-self.graph_line.angle()) self.end_arrow_item.setBrush(line_color) self.end_arrow_item.setPen(line_color) ## Labels n = len(self._ticks) resize_plot_item_list(self.label_items, n, QGraphicsTextItem, self) resize_plot_item_list(self.label_bg_items, n, QGraphicsRectItem, self) resize_plot_item_list(self.tick_items, n, QGraphicsLineItem, self) test_rect = QRectF(self.graph_line.p1(), self.graph_line.p2()).normalized() test_rect.adjust(-1, -1, 1, 1) n_v = self.graph_line.normalVector().unitVector() if self.title_above: n_p = n_v.p2() - n_v.p1() else: n_p = n_v.p1() - n_v.p2() l_v = self.graph_line.unitVector() l_p = l_v.p2() - l_v.p1() for i in range(n): pos, text, size, step = self._ticks[i] hs = 0.5 * step tick_pos = self.map_to_graph(pos) if not test_rect.contains(tick_pos): self.tick_items[i].setVisible(False) self.label_items[i].setVisible(False) continue item = self.label_items[i] item.setVisible(True) if not zoom_only: if self.id in XAxes or getattr(self, 'is_horizontal', False): item.setHtml('<center>' + Qt.escape(text.strip()) + '</center>') else: item.setHtml(Qt.escape(text.strip())) item.setTextWidth(-1) text_angle = 0 if dense_text: w = min(item.boundingRect().width(), self.max_text_width) item.setTextWidth(w) if self.title_above: label_pos = tick_pos + n_p * ( w + self.text_margin ) + l_p * item.boundingRect().height() / 2 else: label_pos = tick_pos + n_p * self.text_margin + l_p * item.boundingRect( ).height() / 2 text_angle = -90 if self.title_above else 90 else: w = min( item.boundingRect().width(), QLineF(self.map_to_graph(pos - hs), self.map_to_graph(pos + hs)).length()) label_pos = tick_pos + n_p * self.text_margin - l_p * w / 2 item.setTextWidth(w) if not self.always_horizontal_text: if self.title_above: item.setRotation(-self.graph_line.angle() - text_angle) else: item.setRotation(self.graph_line.angle() - text_angle) item.setPos(label_pos) item.setDefaultTextColor(text_color) self.label_bg_items[i].setRect(item.boundingRect()) self.label_bg_items[i].setPen(QPen(Qt.NoPen)) self.label_bg_items[i].setBrush(self.plot.color(OWPalette.Canvas)) item = self.tick_items[i] item.setVisible(True) tick_line = QLineF(v) tick_line.translate(-tick_line.p1()) tick_line.setLength(size) if self.title_above: tick_line.setAngle(tick_line.angle() + 180) item.setLine(tick_line) item.setPen(line_color) item.setPos(self.map_to_graph(pos))
def update(self, zoom_only = False): self.update_ticks() line_color = self.plot.color(OWPalette.Axis) text_color = self.plot.color(OWPalette.Text) if not self.graph_line or not self.scene(): return self.line_item.setLine(self.graph_line) self.line_item.setPen(line_color) if self.title: self.title_item.setHtml('<b>' + self.title + '</b>') self.title_item.setDefaultTextColor(text_color) if self.title_location == AxisMiddle: title_p = 0.5 elif self.title_location == AxisEnd: title_p = 0.95 else: title_p = 0.05 title_pos = self.graph_line.pointAt(title_p) v = self.graph_line.normalVector().unitVector() dense_text = False if hasattr(self, 'title_margin'): offset = self.title_margin elif self._ticks: if self.should_be_expanded(): offset = 55 dense_text = True else: offset = 35 else: offset = 10 if self.title_above: title_pos = title_pos + (v.p2() - v.p1())*(offset + QFontMetrics(self.title_item.font()).height()) else: title_pos = title_pos - (v.p2() - v.p1())*offset ## TODO: Move it according to self.label_pos self.title_item.setVisible(self.show_title) self.title_item.setRotation(-self.graph_line.angle()) c = self.title_item.mapToParent(self.title_item.boundingRect().center()) tl = self.title_item.mapToParent(self.title_item.boundingRect().topLeft()) self.title_item.setPos(title_pos - c + tl) ## Arrows if not zoom_only: if self.start_arrow_item: self.scene().removeItem(self.start_arrow_item) self.start_arrow_item = None if self.end_arrow_item: self.scene().removeItem(self.end_arrow_item) self.end_arrow_item = None if self.arrows & AxisStart: if not zoom_only or not self.start_arrow_item: self.start_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.start_arrow_item.setPos(self.graph_line.p1()) self.start_arrow_item.setRotation(-self.graph_line.angle() + 180) self.start_arrow_item.setBrush(line_color) self.start_arrow_item.setPen(line_color) if self.arrows & AxisEnd: if not zoom_only or not self.end_arrow_item: self.end_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.end_arrow_item.setPos(self.graph_line.p2()) self.end_arrow_item.setRotation(-self.graph_line.angle()) self.end_arrow_item.setBrush(line_color) self.end_arrow_item.setPen(line_color) ## Labels n = len(self._ticks) resize_plot_item_list(self.label_items, n, QGraphicsTextItem, self) resize_plot_item_list(self.label_bg_items, n, QGraphicsRectItem, self) resize_plot_item_list(self.tick_items, n, QGraphicsLineItem, self) test_rect = QRectF(self.graph_line.p1(), self.graph_line.p2()).normalized() test_rect.adjust(-1, -1, 1, 1) n_v = self.graph_line.normalVector().unitVector() if self.title_above: n_p = n_v.p2() - n_v.p1() else: n_p = n_v.p1() - n_v.p2() l_v = self.graph_line.unitVector() l_p = l_v.p2() - l_v.p1() for i in range(n): pos, text, size, step = self._ticks[i] hs = 0.5 * step tick_pos = self.map_to_graph( pos ) if not test_rect.contains(tick_pos): self.tick_items[i].setVisible(False) self.label_items[i].setVisible(False) continue item = self.label_items[i] item.setVisible(True) if not zoom_only: if self.id in XAxes or getattr(self, 'is_horizontal', False): item.setHtml( '<center>' + Qt.escape(text.strip()) + '</center>') else: item.setHtml(Qt.escape(text.strip())) item.setTextWidth(-1) text_angle = 0 if dense_text: w = min(item.boundingRect().width(), self.max_text_width) item.setTextWidth(w) if self.title_above: label_pos = tick_pos + n_p * (w + self.text_margin) + l_p * item.boundingRect().height()/2 else: label_pos = tick_pos + n_p * self.text_margin + l_p * item.boundingRect().height()/2 text_angle = -90 if self.title_above else 90 else: w = min(item.boundingRect().width(), QLineF(self.map_to_graph(pos - hs), self.map_to_graph(pos + hs) ).length()) label_pos = tick_pos + n_p * self.text_margin - l_p * w/2 item.setTextWidth(w) if not self.always_horizontal_text: if self.title_above: item.setRotation(-self.graph_line.angle() - text_angle) else: item.setRotation(self.graph_line.angle() - text_angle) item.setPos(label_pos) item.setDefaultTextColor(text_color) self.label_bg_items[i].setRect(item.boundingRect()) self.label_bg_items[i].setPen(QPen(Qt.NoPen)) self.label_bg_items[i].setBrush(self.plot.color(OWPalette.Canvas)) item = self.tick_items[i] item.setVisible(True) tick_line = QLineF(v) tick_line.translate(-tick_line.p1()) tick_line.setLength(size) if self.title_above: tick_line.setAngle(tick_line.angle() + 180) item.setLine( tick_line ) item.setPen(line_color) item.setPos(self.map_to_graph(pos))