class Winform(QWidget): def __init__(self,parent=None): super(Winform,self).__init__(parent) self.setWindowTitle("双缓冲绘图例子") self.pix = QPixmap() self.lastPoint = QPoint() self.endPoint = QPoint() # 辅助画布 self.tempPix = QPixmap() # 标志是否正在绘图 self.isDrawing = False self.initUi() def initUi(self): #窗口大小设置为600*500 self.resize(600, 500); # 画布大小为400*400,背景为白色 self.pix = QPixmap(400, 400); self.pix.fill(Qt.white); def paintEvent(self,event): painter = QPainter(self) x = self.lastPoint.x() y = self.lastPoint.y() w = self.endPoint.x() - x h = self.endPoint.y() - y # 如果正在绘图,就在辅助画布上绘制 if self.isDrawing : # 将以前pix中的内容复制到tempPix中,保证以前的内容不消失 self.tempPix = self.pix pp = QPainter( self.tempPix) pp.drawRect(x,y,w,h) painter.drawPixmap(0, 0, self.tempPix) else : pp = QPainter(self.pix ) pp.drawRect(x, y, w, h) painter.drawPixmap(0, 0, self.pix) def mousePressEvent(self, event) : # 鼠标左键按下 if event.button() == Qt.LeftButton : self.lastPoint = event.pos() self.endPoint = self.lastPoint self.isDrawing = True def mouseReleaseEvent( self, event): # 鼠标左键释放 if event.button() == Qt.LeftButton : self.endPoint = event.pos() #进行重新绘制 self.update() self.isDrawing = False
class Bullet: """Bullet contains: 1 StartPosition 2 EndPosition 3 Color 4 Text( A String) 5 Duration It uses the "window" to draw it selft """ #这个叫做 类的属性 Count=0# 通过类名Bullet.bullet访问,就是一个静态变量 Height=GLOBAL.BULLETFONTSIZE+6 #一个Bullet占用的像素高度 def __init__(self, Text, Color,Duration): Bullet.Count+=1 #这个里面self给定的内容则只属于当前对象 self.Text=Text self.Color=Color self.Duration=Duration*1000 #单位是毫秒,输入的是秒 self.IsExpired=False """this method must be called when this bullet is ready to shoot at the first time """ def prepare(self): self.elapsedTimer=QElapsedTimer() self.elapsedTimer.start() #start time self.StartPosition=QPoint(GLOBAL.WINDOWWIDTH+random.randrange(200,500,20),\ (Bullet.Height+(Bullet.Count%(GLOBAL.WINDOWHEIGHT//Bullet.Height))*Bullet.Height)) self.EndPosition=QPoint(-2000 ,self.StartPosition.y()) """Draw this bullet at position x,y ,use painter Returns True indicates this bullet is out of screen """ def draw(self,painter): ratio=self.elapsedTimer.elapsed()/self.Duration if(ratio>0.9): self.IsExpired=True # pos=ratio*self.EndPosition+(1-ratio)*self.StartPosition pos=QPoint(ratio*self.EndPosition.x()+(1-ratio)*self.StartPosition.x(),self.StartPosition.y()) #这里需要插入绘制字体阴影的代码 # # font.setFixedPitch(True) # painter.setFont(font) painter.save() painter.drawText(pos+QPoint(2,2),self.Text) painter.setPen(QPen(self.Color)) painter.drawText(pos,self.Text) painter.restore() # def __del__(self): # Count-=1 # print ("刚刚自动Delete了一个bullet\n")
def draw_item(self, face, painter): is_draw = True if self.is_clipping: is_draw = self.sphere.is_face_visible(face) if is_draw: polygon = QPolygon() for index, point_index in enumerate(face): p1_x = int(self.sphere.geom.points[face[index-1]][0]) p1_y = int(self.sphere.geom.points[face[index-1]][1]) p1_z = int(self.sphere.geom.points[face[index-1]][2]) p2_x = int(self.sphere.geom.points[point_index][0]) p2_y = int(self.sphere.geom.points[point_index][1]) p2_z = int(self.sphere.geom.points[point_index][2]) if self.sphere.projection_name == "front": # Фронтальная проекция (вид спереди) -> z = 0 real_p1 = QPoint(p1_x, p1_y) real_p2 = QPoint(p2_x, p2_y) elif self.sphere.projection_name == "horizontal": # Горизонтальная проекция (вид сверху) -> y = 0 real_p1 = QPoint(p1_x, p1_z) real_p2 = QPoint(p2_x, p2_z) elif self.sphere.projection_name == "profile": # Профильная проекция (вид сбоку) -> x = 0 real_p1 = QPoint(p1_y, p1_z) real_p2 = QPoint(p2_y, p2_z) else: real_p1 = QPoint(p1_x, p1_y) real_p2 = QPoint(p2_x, p2_y) # Точки для проволочного рисования real_p1.setX(self.width()/2 + real_p1.x()) real_p1.setY(self.height()/2 - real_p1.y()) real_p2.setX(self.width()/2 + real_p2.x()) real_p2.setY(self.height()/2 - real_p2.y()) # Полигоны для рисования с цветом polygon.append(real_p1) polygon.append(real_p2) if not self.is_light: painter.drawLine(real_p1, real_p2) if self.is_light: painter.setBrush(self.sphere.get_face_light(face, self.faces_color)) painter.drawPolygon(polygon)
def click(): window_name = get_window_name() query_value = get_query_value() automation_type = get_query_automation_type() widget = find_widget(window_name, query_value, automation_type) if widget is None: return {} if isinstance(widget, QWidget): clicker.click_on(widget) return get_widget_json(widget) if isinstance(widget, QQuickItem): pointf = widget.mapToScene(QPointF(0.0, 0.0)) x = pointf.x() y = pointf.y() x += qml_method_or_default(widget, "width", 0.0) / 2.0 y += qml_method_or_default(widget, "height", 0.0) / 2.0 window_name = get_window_name() root_widget = get_root_widget(window_name) point = QPoint(x,y) quick_widget = root_widget.childAt(point.x(), point.y()) clicker.click_on(quick_widget, point) return get_widget_json(widget) return {}
class CanvasView(QtCanvasView): itemClickedSignal = pyqtSignal(QtCanvasItem) itemMovedSignal = pyqtSignal(QtCanvasItem) def __init__(self, arg1=None, arg2=None): if type(arg1)==QtCanvas: super(CanvasView, self).__init__(arg1, arg2) else: super(CanvasView, self).__init__(arg1) self.moving = QtCanvasItem(None) self.moving_start = QPoint() def contentsMousePressEvent(self, event): self.handleMouseClickEvent(event) def contentsMouseDoubleClickEvent(self, event): self.handleMouseClickEvent(event) def handleMouseClickEvent(self, event): p = self.inverseWorldMatrix().map(event.pos()) l = self.canvas().collisions(p) self.moving = QtCanvasItem(None) if (not l.isEmpty()): self.moving = l.first() self.moving_start = p self.itemClickedSignal.emit(self.moving) def contentsMouseMoveEvent(self, event): if (self.moving): p = self.inverseWorldMatrix().map(event.pos()) self.moving.moveBy(p.x() - self.moving_start.x(), p.y() - self.moving_start.y()) self.moving_start = p self.canvas().update() self.itemMovedSignal.emit(self.moving)
def snapToGrid(self, position): #Return position of closest grid point gridSizeX = 40 gridSizeY = 20 curPos = QPoint(position.x(), position.y()) gridPos = QPoint(round(curPos.x() / gridSizeX) * gridSizeX, round(curPos.y() / gridSizeY) * gridSizeY) return gridPos
class Winform(QWidget): def __init__(self,parent=None): super(Winform,self).__init__(parent) self.setWindowTitle("绘制矩形图形例子") self.pix = QPixmap() self.lastPoint = QPoint() self.endPoint = QPoint() self.initUi() def initUi(self): #窗口大小设置为600*500 self.resize(600, 500) # 画布大小为400*400,背景为白色 self.pix = QPixmap(400, 400) self.pix.fill(Qt.white) def paintEvent(self,event): painter = QPainter(self) x = self.lastPoint.x() y = self.lastPoint.y() w = self.endPoint.x() - x h = self.endPoint.y() - y pp = QPainter(self.pix) pp.drawRect(x, y, w, h) painter.drawPixmap(0, 0, self.pix) def mousePressEvent(self, event) : # 鼠标左键按下 if event.button() == Qt.LeftButton : self.lastPoint = event.pos() self.endPoint = self.lastPoint def mouseMoveEvent(self, event): # 鼠标左键按下的同时移动鼠标 if event.buttons() and Qt.LeftButton : self.endPoint = event.pos() #进行重新绘制 self.update() def mouseReleaseEvent( self, event): # 鼠标左键释放 if event.button() == Qt.LeftButton : self.endPoint = event.pos() #进行重新绘制 self.update()
def get_linear_gradient(self): fontHeight = self.fontMetrics().height() startPoint = QPoint(self.rect().x(), self.rect().y() + 0.5 * (self.rect().height() - fontHeight)) endPoint = QPoint(startPoint.x(), startPoint.y() + fontHeight) linear = QLinearGradient(startPoint, endPoint) colorCounts = len(self.colors) for i in range(colorCounts): linear.setColorAt(0.2 + i / colorCounts, self.colors[i]) return linear
def kineticMove(self, oldx, oldy, newx, newy ): """Start a kinetic move from (oldx, oldy) to (newx, newy)""" if newx == oldx and newy == oldy: return speed = QPoint(0,0) # solve speed*(speed+1)/2 = delta to ensure 1+2+3+...+speed is as close as possible under delta.. speed.setX((sqrt(1+8*abs(newx-oldx))-1)/2) speed.setY((sqrt(1+8*abs(newy-oldy))-1)/2) # compute the amount of displacement still needed because we're dealing with integer values. diff = QPoint(0,0) diff.setX((speed.x() * (speed.x() + 1) // 2) - abs(newx - oldx)) diff.setY((speed.y() * (speed.y() + 1) // 2) - abs(newy - oldy)) # Since this function is called for exact moves (not free scrolling) # limit the kinetic time to 2 seconds, which means 100 ticks, 5050 pixels. if speed.y() > 100: speed.setY(100) diff.setY(-abs(newy-oldy) + 5050) # Although it is less likely to go beyond that limit for horizontal scrolling, # do it for x as well. if speed.x() > 100: speed.setX(100) diff.setX(-abs(newx-oldx) + 5050) # move left or right, up or down if newx > oldx : speed.setX(-speed.x()) diff.setX(-diff.x()) if newy > oldy : speed.setY(-speed.y()) diff.setY(-diff.y()) # move immediately by the step that cannot be handled by kinetic scrolling. # By construction that step is smaller that the initial speed value. self.fastScrollBy(diff) self.kineticStart(speed)
def wave(self): # print(points[0][0] ,'<', points[1][0], 'and', points[0][1], '>', points[1][1]) t = self.machine.getTransition(self.t_active) init = QPoint(t.getOrig()[0], t.getOrig()[1]) end = QPoint(t.getDest()[0], t.getDest()[1]) angle = t.getAngle() print('processing transition', t.id, t.orig, t.dest) while t.isActive(): self.pts = [[init.x(), init.y()], [end.x(), end.y()]] if self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: self.sumPoint(angle)
def wave(self): t = self.machine.getActiveTransition() if t != None: init = QPoint(t.getOrig()[0], t.getOrig()[1]) end = QPoint(t.getDest()[0], t.getDest()[1]) angle = t.getAngle() #print('processing transition', t.id, t.orig, t.dest) while t.isActive(): #for i in range(3): #for testing self.pts = [[init.x(), init.y()], [end.x(), end.y()]] if self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: self.sumPoint(angle)
def setOffset(self, offset): # Clamp the offset within the offset bounds newOffset = QPoint(min(self.mOffsetBounds.right(), max(self.mOffsetBounds.left(), offset.x())), min(self.mOffsetBounds.bottom(), max(self.mOffsetBounds.top(), offset.y()))) if (self.mOffset != newOffset): xChanged = self.mOffset.x() != newOffset.x() yChanged = self.mOffset.y() != newOffset.y() self.mOffset = newOffset if (xChanged): self.offsetXChanged.emit(self.mOffset.x()) if (yChanged): self.offsetYChanged.emit(self.mOffset.y()) self.offsetChanged.emit(self.mOffset) self.update()
def enemyClick(self, enemy): # Opens an info screen on the enemy if self.parent.gameover == False and enemy.isDead == False: if self.parent.isTowerSelected == False: # self.statusBarMessage("Enemy clicked") self.enemyPopUp = QFrame() self.enemyPopUp.setGeometry(500, 500, 100, 100) grid = QGridLayout() self.enemyPopUp.setLayout(grid) enemyStats = QLabel("Enemy Stats") name = QLabel("Name: " + str(enemy.name)) speed = QLabel("Speed: " + str(enemy.speed)) health = QLabel("Health: {:.0f}".format(enemy.health)) pixmap = QLabel() pixmap.setPixmap(enemy.picture) vbox = QVBoxLayout() vbox.addWidget(enemyStats) vbox.addWidget(name) vbox.addWidget(speed) vbox.addWidget(health) grid.addLayout(vbox, 0, 0) vbox2 = QVBoxLayout() vbox2.addWidget(pixmap) vbox2.addStretch() doneButton = QPushButton("Done") vbox2.addWidget(doneButton) grid.addLayout(vbox2, 0, 1) location = QPoint(QCursor.pos()) self.enemyPopUp.move(location.x() - 100, location.y()) self.enemyPopUp.show() doneButton.clicked.connect(self.enemyPopUp.hide) elif self.parent.gameover == True: self.statusBarMessage("The game has ended. Stop doing stuff.")
def download(self): grab = None for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(self._tilesRect.topLeft() + QPoint(x, y)) if tp not in self._tilePixmaps: grab = QPoint(tp) break if grab is None: self._url = QUrl() return path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % (self.zoom, grab.x(), grab.y()) self._url = QUrl(path) request = QNetworkRequest() request.setUrl(self._url) request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0') request.setAttribute(QNetworkRequest.User, grab) self._manager.get(request)
def mouseMoveEvent(self, event): if event.buttons() == Qt.RightButton: # write the relative cursor position to mime data mimeData = QMimeData() # simple string with 'x,y' mimeData.setText('%d,%d' % (event.x(), event.y())) # let's make it fancy. we'll show a "ghost" of the button as we drag # grab the button to a pixmap pixmap = self.grab() # below makes the pixmap half transparent painter = QPainter(pixmap) painter.setCompositionMode(painter.CompositionMode_DestinationIn) painter.fillRect(pixmap.rect(), QColor(0, 0, 0, 127)) painter.end() # make a QDrag drag = QDrag(self) # put our MimeData drag.setMimeData(mimeData) # set its Pixmap drag.setPixmap(pixmap) # shift the Pixmap so that it coincides with the cursor position drag.setHotSpot(event.pos()) # start the drag operation # exec_ will return the accepted action from dropEvent if drag.exec_(Qt.CopyAction | Qt.MoveAction) == Qt.MoveAction: print('moved') else: print('copied:'+str(event.globalPos())) #self.move(event.pos()) elif event.buttons() == Qt.LeftButton: delta = QPoint(event.globalPos() - self.oldPos) self.move(self.frameGeometry().x() + delta.x(), self.frameGeometry().y() + delta.y()) self.oldPos = event.globalPos()
class SlippyMap(QObject): updated = pyqtSignal(QRect) def __init__(self, parent=None): super(SlippyMap, self).__init__(parent) self._offset = QPoint() self._tilesRect = QRect() self._tilePixmaps = {} # Point(x, y) to QPixmap mapping self._manager = QNetworkAccessManager() self._url = QUrl() # public vars self.width = 400 self.height = 300 self.zoom = 15 self.latitude = 59.9138204 self.longitude = 10.7387413 self._emptyTile = QPixmap(TDIM, TDIM) self._emptyTile.fill(Qt.lightGray) cache = QNetworkDiskCache() cache.setCacheDirectory( QStandardPaths.writableLocation(QStandardPaths.CacheLocation)) self._manager.setCache(cache) self._manager.finished.connect(self.handleNetworkData) def invalidate(self): if self.width <= 0 or self.height <= 0: return ct = tileForCoordinate(self.latitude, self.longitude, self.zoom) tx = ct.x() ty = ct.y() # top-left corner of the center tile xp = int(self.width / 2 - (tx - math.floor(tx)) * TDIM) yp = int(self.height / 2 - (ty - math.floor(ty)) * TDIM) # first tile vertical and horizontal xa = (xp + TDIM - 1) / TDIM ya = (yp + TDIM - 1) / TDIM xs = int(tx) - xa ys = int(ty) - ya # offset for top-left tile self._offset = QPoint(xp - xa * TDIM, yp - ya * TDIM) # last tile vertical and horizontal xe = int(tx) + (self.width - xp - 1) / TDIM ye = int(ty) + (self.height - yp - 1) / TDIM # build a rect self._tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1) if self._url.isEmpty(): self.download() self.updated.emit(QRect(0, 0, self.width, self.height)) def render(self, p, rect): for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(x + self._tilesRect.left(), y + self._tilesRect.top()) box = self.tileRect(tp) if rect.intersects(box): p.drawPixmap(box, self._tilePixmaps.get(tp, self._emptyTile)) def pan(self, delta): dx = QPointF(delta) / float(TDIM) center = tileForCoordinate(self.latitude, self.longitude, self.zoom) - dx self.latitude = latitudeFromTile(center.y(), self.zoom) self.longitude = longitudeFromTile(center.x(), self.zoom) self.invalidate() # slots def handleNetworkData(self, reply): img = QImage() tp = Point(reply.request().attribute(QNetworkRequest.User)) url = reply.url() if not reply.error(): if img.load(reply, None): self._tilePixmaps[tp] = QPixmap.fromImage(img) reply.deleteLater() self.updated.emit(self.tileRect(tp)) # purge unused tiles bound = self._tilesRect.adjusted(-2, -2, 2, 2) for tp in list(self._tilePixmaps.keys()): if not bound.contains(tp): del self._tilePixmaps[tp] self.download() def download(self): grab = None for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(self._tilesRect.topLeft() + QPoint(x, y)) if tp not in self._tilePixmaps: grab = QPoint(tp) break if grab is None: self._url = QUrl() return path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % (self.zoom, grab.x(), grab.y()) self._url = QUrl(path) request = QNetworkRequest() request.setUrl(self._url) request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0') request.setAttribute(QNetworkRequest.User, grab) self._manager.get(request) def tileRect(self, tp): t = tp - self._tilesRect.topLeft() x = t.x() * TDIM + self._offset.x() y = t.y() * TDIM + self._offset.y() return QRect(x, y, TDIM, TDIM)
def createCurveIcons(self): pix = QPixmap(self.m_iconSize) painter = QPainter() gradient = QLinearGradient(0, 0, 0, self.m_iconSize.height()) gradient.setColorAt(0.0, QColor(240, 240, 240)) gradient.setColorAt(1.0, QColor(224, 224, 224)) brush = QBrush(gradient) # The original C++ code uses undocumented calls to get the names of the # different curve types. We do the Python equivalant (but without # cheating). curve_types = [(n, c) for n, c in QEasingCurve.__dict__.items() if isinstance(c, QEasingCurve.Type) and c != QEasingCurve.Custom] curve_types.sort(key=lambda ct: ct[1]) painter.begin(pix) for curve_name, curve_type in curve_types: painter.fillRect(QRect(QPoint(0, 0), self.m_iconSize), brush) curve = QEasingCurve(curve_type) if curve_type == QEasingCurve.BezierSpline: curve.addCubicBezierSegment(QPointF(0.4, 0.1), QPointF(0.6, 0.9), QPointF(1.0, 1.0)) elif curve_type == QEasingCurve.TCBSpline: curve.addTCBSegment(QPointF(0.0, 0.0), 0, 0, 0) curve.addTCBSegment(QPointF(0.3, 0.4), 0.2, 1, -0.2) curve.addTCBSegment(QPointF(0.7, 0.6), -0.2, 1, 0.2) curve.addTCBSegment(QPointF(1.0, 1.0), 0, 0, 0) painter.setPen(QColor(0, 0, 255, 64)) xAxis = self.m_iconSize.height() / 1.5 yAxis = self.m_iconSize.width() / 3.0 painter.drawLine(0, xAxis, self.m_iconSize.width(), xAxis) painter.drawLine(yAxis, 0, yAxis, self.m_iconSize.height()) curveScale = self.m_iconSize.height() / 2.0; painter.setPen(Qt.NoPen) # Start point. painter.setBrush(Qt.red) start = QPoint(yAxis, xAxis - curveScale * curve.valueForProgress(0)) painter.drawRect(start.x() - 1, start.y() - 1, 3, 3) # End point. painter.setBrush(Qt.blue) end = QPoint(yAxis + curveScale, xAxis - curveScale * curve.valueForProgress(1)) painter.drawRect(end.x() - 1, end.y() - 1, 3, 3) curvePath = QPainterPath() curvePath.moveTo(QPointF(start)) t = 0.0 while t <= 1.0: to = QPointF(yAxis + curveScale * t, xAxis - curveScale * curve.valueForProgress(t)) curvePath.lineTo(to) t += 1.0 / curveScale painter.setRenderHint(QPainter.Antialiasing, True) painter.strokePath(curvePath, QColor(32, 32, 32)) painter.setRenderHint(QPainter.Antialiasing, False) item = QListWidgetItem() item.setIcon(QIcon(pix)) item.setText(curve_name) self.m_ui.easingCurvePicker.addItem(item) painter.end()
def move(self, a0: QtCore.QPoint): super().move(a0.x() - 15, a0.y() - 15)
class Example(QWidget): overlay: QImage #Overlay(Накладываем) Picture on Window timer: QTimer #Timet init painter: QPainter Colors: list arr_points: list DeltaX: int DeltaY: int SelfHeight: int LastAngle: int stationSize: list LastMousePosition: QPoint AllData: pd.DataFrame toolTipWidget: QLabel def __init__(self): super().__init__() self.initUI() def keyPressEvent(self, event): if event.key() == 16777216: #Esc #self.FileSaving(self.arr_points, FILE_NAME) sys.exit() #Programm Closing elif event.key() == 16777249: #Ctrl + R stationsName = self.FileReading(FILE_STATIONS_NAME) self.FileSaving(self.GetGoogleData(stationsName), FILE_DATA_NAME) def GetStationPopularity(self, station_name, trends_object): kw_list = station_name trends_object.build_payload(kw_list, cat=0, timeframe='today 5-y', geo='', gprop='') interest = trends_object.interest_over_time() return interest.mean()[0] #plt.plot(interest[station_name]) #plt.show() def mousePressEvent(self, event): mousePoint = event.pos() self.LastMousePosition = mousePoint if event.button() == 1: # self.painter.setFont(QFont('Arial', 111)) # self.painter.drawText(QPoint(200,200), 'HELLO') self.toolTipWidget.setText(' testtestetstetstestete ') self.toolTipWidget.move(event.pos()) #self.toolTipWidget.adjustSize() self.toolTipWidget.show() if event.button() == 2: WindowW = self.frameGeometry().width() # WindowSize WindowH = self.frameGeometry().height() # WindowSize imgH = self.overlay.height() # Original Picture Size imgW = self.overlay.width() # Original Picture Size img = self.overlay.scaledToHeight(self.SelfHeight, Qt.FastTransformation) #AdjX = (WindowW-img.width())/2 ResultX = imgW * (mousePoint.x() - self.DeltaX) / img.width() ResultY = imgH / 100 * ((mousePoint.y() - self.DeltaY) / (self.SelfHeight / 100)) #eraser = 7 self.painter.drawEllipse(QPoint(ResultX, ResultY), RADIUS, RADIUS) #self.painter.eraseRect(QRect(QPoint(ResultX-RADIUS/2-eraser, ResultY-RADIUS/2-eraser), QPoint(ResultX+radius/2+eraser, ResultY+radius/2+eraser))) self.arr_points.append((ResultX, ResultY)) #print([(round(x[0]), round(x[1])) for x in self.arr_points]) self.update() #Redraw def mouseReleaseEvent(self, event): self.point = None self.toolTipWidget.hide() def FileSaving(self, arr: list, fileName: str): with open(fileName, 'w') as f: for item in arr: f.write(';'.join(str(x) for x in item) + '\n') f.close() def FileReading(self, fileName: str): with open(fileName, 'r') as f: names = f.read().split('\n') f.close() #print(names) return [x.split(';') for x in names] def GetGoogleData(self, namesSt: list): stationSizes = [] for station in namesSt: sz = self.GetStationPopularity([station], self.pytrends) if sz > 0: stationSizes.append([station, sz]) print(station + ': ' + str(round(sz, 1))) else: print(station + ' error') return stationSizes def FileDrawing(self, fileName: str): penLine = QPen(QColor(Qt.red)) penLine.setWidth(10) #my_file = Path('!StationsLine12.txt') #print(my_file.isfile()) allDataI = 0 for n in range(14 * 2): penEllipse = QPen(self.Colors[int(n / 2)]) penEllipse.setWidth(5) data = [] path = fileName + str(n / 2 + 1) + '.txt' my_file = Path(path) #print(os.listdir()) if my_file.is_file(): with open(fileName + str(n / 2 + 1) + '.txt', 'r') as f: data = f.read().split('\n') f.close() lastX = None lastY = None Point1 = None Point2 = None Startlen = None x = 0 y = 0 i = 0 #print(self.NameReading('!Stations.txt')) for line in data: x, y = line.split(';') # self.AllData[allDataI].append(x) #self.AllData[allDataI].append(y) #if lastX is not None or lastY is not None: self.painter.setPen(penLine) #Point1 = QPoint(lastX, lastY) #Point2 = QPoint(float(x), float(y)) #self.painter.drawLine(Point1, Point2) self.painter.setPen(penEllipse) penLine = QPen(QColor(Qt.red)) self.painter.setBrush(QColor(Qt.white)) # CircleSize = (RADIUS/100) * float(self.AllData[i][1]) + ADDITIONAL CircleSize = 20 #print(CircleSize) #if n == 8 and i>=11 and i<=12: self.painter.drawEllipse( float(x) - CircleSize, float(y) - CircleSize, CircleSize * 2, CircleSize * 2) i += 1 allDataI += 1 def closeEvent(self, event): #self.FileSaving(self.arr_points, FILE_NAME) sys.exit() #Programm Closing def initUI(self): self.Colors = [ QColor(228, 37, 24), #1 QColor(75, 175, 79), #2 QColor(5, 114, 185), #3 QColor(36, 188, 239), #4 QColor(146, 82, 51), #5 QColor(239, 128, 39), #6 QColor(148, 63, 144), #7 QColor(255, 209, 30), #8 QColor(173, 172, 172), #9 QColor(185, 206, 31), #10 QColor(134, 204, 206), #11 QColor(186, 200, 232), #12 QColor(68, 143, 201), #13 QColor(232, 68, 57), #14 ] self.pytrends = TrendReq(hl='en-US', tz=360) self.showMaximized() #self.showNormal() self.setStyleSheet("background-color: white;") self.toolTipWidget = QLabel() # self.toolTipWidget.setFrameShape(QFrame.StyleSheet) self.toolTipWidget.setStyleSheet("background-color: rgb(255,255,225);") self.toolTipWidget.setWindowFlags(Qt.ToolTip) self.toolTipWidget.setAttribute(Qt.WA_TransparentForMouseEvents) self.toolTipWidget.hide() self.arr_points = [] self.stationSize = [] self.LastAngle = 0 self.timer = QTimer() #Timer init self.timer.timeout.connect(self.update) # Timer init self.setWindowTitle('Moscow Metro Map Poppularity') # Title self.point = None self.DeltaX = 0 self.DeltaY = 0 self.SelfHeight = self.frameGeometry().height() self.LastMousePosition = QPoint(0, 0) self.overlay = QImage() self.overlay.load('Moscow Metro Map Stations Popularity\\MainMap.bmp') pen = QPen(QColor(Qt.red)) pen.setWidth(5) self.painter = QPainter(self.overlay) self.painter.setPen(pen) self.painter.Antialiasing = True self.timer.start(1000 / 50) #50 кадров в секунду #self.AllData = self.FileReading(FILE_DATA_NAME) self.AllData = pd.read_csv(FILE_DATA_NAME) #self.arr_points = self.FileReading() self.FileDrawing(FILE_NAME) def paintEvent(self, event): painter = QPainter() painter.begin(self) #windowsWidth = self.frameGeometry().width() windowsHeight = self.frameGeometry().height() img = self.overlay.scaledToHeight(self.SelfHeight, 0) painter.drawImage(self.DeltaX, self.DeltaY, img) painter.end() del painter def mouseMoveEvent(self, event): CurentPos = event.pos() self.DeltaX -= self.LastMousePosition.x() - CurentPos.x() self.DeltaY -= self.LastMousePosition.y() - CurentPos.y() #self.LastMousePosition = mousePoint self.LastMousePosition = event.pos() def wheelEvent(self, event): #print(str(event.angleDelta())) self.SelfHeight += (event.angleDelta().y()) / 10 self.LastAngle = event.angleDelta().y() def resizeEvent(self, event): self.SelfHeight = self.frameGeometry().height() - 10 if hasattr(self, 'overlay'): img = self.overlay.scaledToHeight(self.SelfHeight, 0) self.DeltaX = (self.frameGeometry().width() - img.width()) / 2 self.DeltaY = 0
class Compass(QWidget): angle_event = pyqtSignal(Angle) def __init__(self, parent=None): super().__init__(parent) self.offset = 75 self.span = self.offset + 525 self.center = QPoint(self.span / 2, self.span / 2) self.setMinimumSize(self.span, self.span) self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.setMouseTracking(True) self.wedges = [] for start in range(0, 360 * 16, 45 * 16): self.wedges.append( CompassWedge( start, self.span, self.span, self.offset, Angle(floor(((360 - start / 16 + 45) % 360) / 45)), self)) deg_font = QFont("Consolas", 22, 2) for deg in range(8): temp = QLabel(self) angle = deg * 45 temp.setText(str(angle) + '°') temp.setFont(deg_font) tw = temp.fontMetrics().boundingRect(temp.text()).width() th = temp.fontMetrics().boundingRect(temp.text()).height() temp.move(self.deg_lbl_pos((180 - angle) % 360, QSize(tw, th))) def deg_lbl_pos(self, angle, size): x_0 = self.center.x() y_0 = self.center.y() size_x = size.width() size_y = size.height() off_x = 0 off_y = 0 dist = self.span / 2 - self.offset + 10 if angle == 0: off_x = -size_x / 2 elif angle == 90: off_y = -size_y / 2 elif angle == 135: off_y = -size_y elif angle == 180: off_x = -size_x / 2 off_y = -size_y elif angle == 225: off_y = -size_y off_x = -size_x elif angle == 270: off_y = -size_y / 2 off_x = -size_x elif angle == 315: off_x = -size_x theta_rad = pi / 2 - radians(angle) return QPoint(round(x_0 + dist * cos(theta_rad) + off_x), round(y_0 + dist * sin(theta_rad) + off_y)) def mouseMoveEvent(self, event): x_1 = event.pos().x() y_1 = event.pos().y() x_2 = self.center.x() y_2 = self.center.y() dist = floor(hypot(x_2 - x_1, y_2 - y_1)) angle = atan2(x_2 - x_1, y_2 - y_1) if dist <= floor(self.span / 2) - self.offset: if 0 <= angle < (2 * pi) / 8: self.activate_wedge(2) elif (2 * pi) / 8 <= angle < 2 * (2 * pi) / 8: self.activate_wedge(3) elif 2 * (2 * pi) / 8 <= angle < 3 * (2 * pi) / 8: self.activate_wedge(4) elif 3 * (2 * pi) / 8 <= angle < 4 * (2 * pi) / 8: self.activate_wedge(5) elif 0 > angle >= -(2 * pi) / 8: self.activate_wedge(1) elif -(2 * pi) / 8 > angle >= -2 * (2 * pi) / 8: self.activate_wedge(0) elif -2 * (2 * pi) / 8 > angle >= -3 * (2 * pi) / 8: self.activate_wedge(7) elif -3 * (2 * pi) / 8 > angle >= -4 * (2 * pi) / 8: self.activate_wedge(6) else: self.activate_wedge(-1) def mouseReleaseEvent(self, event): for wedge in self.wedges: if wedge.active: self.angle_event.emit(wedge.id) wedge.mark(True) def activate_wedge(self, active): for index in range(self.wedges.__len__()): self.wedges[index].activate(True if index == active else False) @pyqtSlot() def clear_state(self): for wedge in self.wedges: wedge.mark(False)
class Transect(QtWidgets.QGraphicsScene): # Initialisation function of the class def __init__(self, mainWindow, imagetoPaint, dataset, rowS, colS, tabWindow): super(Transect, self).__init__() #create the canvas to draw the line on and all its necessary components self.addItem(QGraphicsPixmapItem(imagetoPaint)) self.img = imagetoPaint self.values = [] self.distances = [] self.data = dataset self.pixSpacing = rowS / colS self._start = QPointF() self.drawing = True self._current_rect_item = None self.pos1 = QPoint() self.pos2 = QPoint() self.points = [] self.tabWindow = tabWindow self.mainWindow = mainWindow # This function starts the line draw when the mouse is pressed into the 2D view of the scan def mousePressEvent(self, event): # If is the first time we can draw as we want a line per button press if self.drawing == True: self.pos1 = event.scenePos() self._current_rect_item = QtWidgets.QGraphicsLineItem() self._current_rect_item.setPen(QtCore.Qt.red) self._current_rect_item.setFlag( QtWidgets.QGraphicsItem.ItemIsMovable, False) self.addItem(self._current_rect_item) self._start = event.scenePos() r = QtCore.QLineF(self._start, self._start) self._current_rect_item.setLine(r) # This function tracks the mouse and draws the line from the original press point def mouseMoveEvent(self, event): if self._current_rect_item is not None and self.drawing == True: r = QtCore.QLineF(self._start, event.scenePos()) self._current_rect_item.setLine(r) # This function terminates the line drawing and initiates the plot def mouseReleaseEvent(self, event): if self.drawing == True: self.pos2 = event.scenePos() self.drawDDA(round(self.pos1.x()), round(self.pos1.y()), round(self.pos2.x()), round(self.pos2.y())) self.drawing = False self.plotResult() self._current_rect_item = None # This function performs the DDA algorithm that locates all the points in the drawn line def drawDDA(self, x1, y1, x2, y2): x, y = x1, y1 length = abs(x2 - x1) if abs(x2 - x1) > abs(y2 - y1) else abs(y2 - y1) dx = (x2 - x1) / float(length) dy = (y2 - y1) / float(length) self.points.append((round(x), round(y))) for i in range(length): x += dx y += dy self.points.append((round(x), round(y))) # get the values of these points from the dataset self.getValues() # get their distances for the plot self.getDistances() # This function calculates the distance between two points def calculateDistance(self, x1, y1, x2, y2): dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2) return dist # This function gets the corresponding values of all the points in the drawn line from the dataset def getValues(self): for i, j in self.points: if i in range(512) and j in range(512): self.values.append(self.data[i][j]) # Get the distance of each point from the end of the line def getDistances(self): for i, j in self.points: if i in range(512) and j in range(512): self.distances.append( self.calculateDistance(i, j, round(self.pos2.x()), round(self.pos2.y()))) self.distances.reverse() # This function handles the closing event of the transect graph def on_close(self, event): plt1.close() #returns the main page back to a non-drawing environment self.mainWindow.dicom_view.update_view() event.canvas.figure.axes[0].has_been_closed = True # This function plots the Transect graph into a pop up window def plotResult(self): plt1.close('all') newList = [(x * self.pixSpacing) for x in self.distances] # adding a dummy manager fig1 = plt1.figure(num='Transect Graph') new_manager = fig1.canvas.manager new_manager.canvas.figure = fig1 fig1.set_canvas(new_manager.canvas) ax1 = fig1.add_subplot(111) ax1.has_been_closed = False ax1.step(newList, self.values, where='mid') plt1.xlabel('Distance mm') plt1.ylabel('CT #') plt1.grid(True) fig1.canvas.mpl_connect('close_event', self.on_close) plt1.show()
class SpritesheetViewer(QtWidgets.QFrame): left_mouse_down = False mouse_press_pos = None last_mouse_pos = QPoint(0, 0) spritesheet_image = None animation_data = None bg_image = None bg_tile_num = (120, 108) bg_tile_size = 10 SCALE_DELTA = 1 SCALE_MAX = 10 SCALE_MIN = 1 SCALE_DEFAULT = 1 BOX_SIZE = 10 isPanning = False camera = QPoint(0, 0) sheet_margin = QSize(10, 10) mode = None sizing_handles = None sizing_mode = None scale_changed_signal = pyqtSignal(float) animation_data_changed_signal = pyqtSignal() sizing_handle_cursors = [ Qt.SizeFDiagCursor, Qt.SizeVerCursor, Qt.SizeBDiagCursor, Qt.SizeHorCursor, Qt.SizeFDiagCursor, Qt.SizeVerCursor, Qt.SizeBDiagCursor, Qt.SizeHorCursor ] move_frame_cursor = Qt.SizeAllCursor def __init__(self, parent=None): super(SpritesheetViewer, self).__init__() self.setParent(parent) self.draw_bg_image() self.update() self.show() self.zoom_cursor = QtGui.QCursor(QtGui.QPixmap("icons/zoom.png")) self.zoom_in_cursor = QtGui.QCursor(QtGui.QPixmap("icons/zoom_in.png")) self.zoom_out_cursor = QtGui.QCursor(QtGui.QPixmap("icons/zoom_out.png")) self.scale_label = QtWidgets.QLabel("") self.setMouseTracking(True) self.setFocusPolicy(Qt.ClickFocus) self._scale = self.SCALE_DEFAULT self.original_frame_positions = [] def load_animation_data(self, animation_data): self.animation_data = animation_data self.animation_data.active_sequence_changed.connect(self.handle_sequence_signal) self.animation_data.active_frame_changed.connect(self.handle_frame_signal) self.reset_spritesheet() def renew(self): if self.animation_data is None: return self.calc_sizing_handles() self.update() def reset_spritesheet(self): self.scale = self.SCALE_DEFAULT self.spritesheet_image = QtGui.QImage(self.animation_data.spritesheet_path) self.center_sequence() self.update() @property def scale(self): return self._scale @scale.setter def scale(self, scale): # Get coordinates of mouse relative to viewer scale = max(round(scale, 1), self.SCALE_MIN) scale = min(round(scale, 1), self.SCALE_MAX) scale_diff = scale - self._scale old_camera_size = self.size() / self.scale new_camera_size = self.size() / (self.scale + scale_diff) size_ratio = new_camera_size.width() / old_camera_size.width() mouse = self.view2sheet(self.last_mouse_pos) mouse_ratio_x = (mouse.x() - self.camera.x()) / old_camera_size.width() mouse_ratio_y = (mouse.y() - self.camera.y()) / old_camera_size.height() camera_x = mouse.x() - (new_camera_size.width() * mouse_ratio_x) camera_y = mouse.y() - (new_camera_size.height() * mouse_ratio_y) self._scale = scale self.camera = QPoint(camera_x, camera_y) self.constrain_camera() self.calc_sizing_handles() self.update() self.scale_changed_signal.emit(scale) def draw_bg_image(self): # Prepare an image of background tiles self.bg_image = QtGui.QImage(self.bg_tile_num[0] * self.bg_tile_size, self.bg_tile_num[1] * self.bg_tile_size, QtGui.QImage.Format_Grayscale8) qp = QtGui.QPainter() qp.begin(self.bg_image) for x in range(0, self.bg_tile_num[0]): for y in range(0, self.bg_tile_num[1]): if ((y + x) % 2) == 1: qp.fillRect(x * self.bg_tile_size, y *self.bg_tile_size, self.bg_tile_size, self.bg_tile_size, QtGui.QColor(255, 255, 255)) else: qp.fillRect(x * self.bg_tile_size, y * self.bg_tile_size, self.bg_tile_size, self.bg_tile_size, QtGui.QColor(200, 200, 200)) qp.end() def zoom_in(self): self.scale = self.scale + self.SCALE_DELTA def zoom_out(self): self.scale = self.scale - self.SCALE_DELTA def handle_sequence_signal(self): self.center_sequence() def handle_frame_signal(self): self.calc_sizing_handles() """ EVENTS """ def paintEvent(self, event): qp = QtGui.QPainter() qp.begin(self) qp.setClipRect(0, 0, self.size().width(), self.size().height()) # BACKGROUND tiles if self.bg_image: qp.drawImage(0, 0, self.bg_image) # SPRITESHEET, cut and scaled cutout_size = (math.ceil(self.frameRect().width() / self.scale), math.ceil(self.frameRect().height() / self.scale)) if self.spritesheet_image: ss_cut = self.spritesheet_image.copy(self.camera.x(), self.camera.y(), cutout_size[0], cutout_size[1]) ss_cut = ss_cut.scaled(cutout_size[0] * self.scale, cutout_size[1] * self.scale) qp.drawImage(0, 0, ss_cut) # SELECTION BOXES around frames of sequence if self.animation_data and self.animation_data.active_sequence and self.animation_data.active_sequence.frames: self.draw_frames(qp) #draw MOUSE CROSSHAIR when creating new frames if self.mode == ViewerMode.NEW_FRAME: if self.last_mouse_pos is not None and self.underMouse(): self.draw_crosshair(qp) qp.end() def snap_to_pixels(self, cord): return QPoint(cord.x() - cord.x() % self.scale, cord.y() - cord.y() % self.scale) def draw_crosshair(self, qp): cord = self.snap_to_pixels(self.last_mouse_pos) qp.drawLine(cord.x(), 0, cord.x(), self.size().height()) qp.drawLine(0, cord.y(), self.size().width(), cord.y()) # Debug: draw dot where cursor actualy is qp.drawEllipse(self.last_mouse_pos, 1, 1) rCord = self.view2sheet(self.last_mouse_pos) qp.drawText(cord.x() + 2, cord.y() + 10, "X: %s Y: %s" % (cord.x(), cord.y())) qp.drawText(cord.x() + 2, cord.y() + 20, "rX: %s rY: %s" % (rCord.x(), rCord.y())) def draw_frames(self, qp): qp.setBackgroundMode(Qt.OpaqueMode) black_pen = QtGui.QPen(QtGui.QColor(0, 0, 0)) white_pen = QtGui.QPen(QtGui.QColor(255, 255, 255)) grey_pen = QtGui.QPen(QtGui.QColor("gray")) for sequence in self.animation_data.selected: i = 0 for frame in sequence.frames: # Draw frame border # REPEAT 1 pos = self.sheet2view(frame.topLeft()) size = QSize(round(frame.width() * self.scale), round(frame.height() * self.scale)) qp.setPen(white_pen) qp.setBackground(QtGui.QBrush(QtGui.QColor(0, 0, 0))) #qp.drawText(pos.x(), pos.y() - 2, "POS(%s, %s) SIZE(%s, %s)" % (frame.x(), frame.y(), frame.width(), frame.height())) qp.drawText(pos.x() + 1, pos.y() + 12, str(i)) qp.drawText( pos.x() + 1, pos.y() + size.height() + 12, "WIDTH: %s HEIGHT: %s" % (frame.width(), frame.height()) ) qp.setPen(black_pen) qp.setBackground(QtGui.QBrush(QtGui.QColor(255, 255, 255))) # Draw frame border qp.setBackgroundMode(Qt.TransparentMode) qp.drawRect(pos.x(), pos.y(), size.width(), size.height()) # Rect qp.setBackgroundMode(Qt.OpaqueMode) # Highlight the selected frames if self.mode == ViewerMode.ALTER_SELECTION: # REPEAT 3 a_pos = self.sheet2view(frame.topLeft()) a_size = QSize(round(frame.width() * self.scale), round(frame.height() * self.scale)) if frame in sequence.selected: if frame == sequence.active_frame: colour = QtGui.QColor(180, 215, 255, 100) qp.drawText(a_pos.x(), a_pos.y() - 10, "ACTIVE") else: colour = QtGui.QColor(255, 255, 0, 100) qp.drawText(a_pos.x(), a_pos.y() - 10, "SELECTED") qp.fillRect(a_pos.x() + 1, a_pos.y() + 1, a_size.width() - 1, a_size.height() - 1, colour) i += 1 if self.mode == ViewerMode.ALTER_SELECTION: a_frame = self.animation_data.active_frame mods = QtWidgets.QApplication.keyboardModifiers() if mods & Qt.ControlModifier: shift = self.sheet2view( QPoint( a_frame.x() + a_frame.shift.x(), a_frame.y() + a_frame.shift.y() ) ) circle_radius = 5 qp.drawEllipse( shift.x() - circle_radius, shift.y() - circle_radius, circle_radius * 2, circle_radius * 2 ) qp.drawLine( shift.x(), shift.y() + 4, shift.x(), shift.y() - 4 ) qp.drawLine( shift.x() + 4, shift.y(), shift.x() - 4, shift.y() ) else: self.draw_sizing_handles(qp) def calc_sizing_handles(self): if self.animation_data.active_frame is None: return active_frame = self.animation_data.active_frame pos = self.sheet2view(active_frame.topLeft()) size = active_frame.size() * self.scale box_size = self.BOX_SIZE self.sizing_handles = [ QRect(pos.x() - box_size/2, pos.y() - box_size/2, box_size, box_size), # Top Left QRect(pos.x() + size.width()/2 - box_size/2, pos.y() - box_size/2, box_size, box_size), # Top QRect(pos.x() + size.width() - box_size/2, pos.y() - box_size/2, box_size, box_size), # Top Right QRect(pos.x() + size.width() - box_size/2, pos.y() + size.height()/2 - box_size/2, box_size, box_size), # Right QRect(pos.x() + size.width() - box_size/2, pos.y() + size.height() - box_size/2, box_size, box_size), # Bottom Right QRect(pos.x() + size.width()/2 - box_size/2, pos.y() + size.height() - box_size/2, box_size, box_size), # Bottom QRect(pos.x() - box_size/2, pos.y() + size.height() - box_size/2, box_size, box_size), # Bottom Left QRect(pos.x() - box_size/2, pos.y() + size.height()/2 - box_size/2, box_size, box_size) # Left ] def draw_sizing_handles(self, qp): if self.sizing_handles is None: return if self.animation_data.active_frame is None or self.animation_data.active_frame not in self.animation_data.active_sequence.selected: return qp.setBrush(QtGui.QBrush(QtGui.QColor(255, 255, 255))) for handle in self.sizing_handles: qp.drawRect(handle) qp.setBrush(QtGui.QBrush()) def focus_selected(self): i = 0 pos_sum = QPoint(0 ,0) for sequence in self.animation_data.selected: for frame in sequence.selected: pos_sum = frame.center() i += 1 self.center_camera(pos_sum / i) def center_sequence(self): if self.animation_data.active_frame is not None: self.center_camera(self.animation_data.active_frame.center()) def center_camera(self, point: QPoint) -> None: """ Centers the camera on a point on the spritesheet""" self.camera = QPoint(point.x() - self.width()/(2*self.scale), point.y() - self.height()/(2*self.scale)) self.constrain_camera() def constrain_camera(self): if self.spritesheet_image is None: return if self.camera.x() < 0: self.camera.setX(0) if self.camera.x() > self.spritesheet_image.width() - (self.frameRect().width() / self.scale): self.camera.setX(self.spritesheet_image.width() - (self.frameRect().width() / self.scale)) if self.camera.y() < 0: self.camera.setY(0) if self.camera.y() > self.spritesheet_image.height() - (self.frameRect().height() / self.scale): self.camera.setY(self.spritesheet_image.height() - (self.frameRect().height() / self.scale)) def focus_alter_frame(self, frame=None): if frame is None: frame = self.animation_data.active_frame if frame is None: return self.center_camera(frame.center()) self.mode = ViewerMode.ALTER_SELECTION self.calc_sizing_handles() self.update() def wheelEvent(self, event): """ Zoom in or out """ # If a spritesheet has not been loaded, do nothing if self.spritesheet_image is None: return # Zoom in / Out of the spritesheet if event.angleDelta().y() > 0: self.zoom_in() else: self.zoom_out() def mousePressEvent(self, mouse): """ Controls for spritesheet manipulation """ if self.isPanning is True or self.spritesheet_image is None: return # Zooming in / out with mouse wheel if mouse.button() == Qt.MidButton or mouse.button() == Qt.RightButton: self.mouse_press_pos = mouse.pos() self.setCursor(Qt.SizeAllCursor) self.camera_old = self.camera self.isPanning = True # Selection of spritesheet pixels if mouse.button() == Qt.LeftButton: self.left_mouse_down = True self.mouse_press_pos = mouse.pos() if self.mode == ViewerMode.ALTER_SELECTION and self.animation_data.active_sequence is not None: mouse_rel = self.view2sheet(mouse.pos()) # If sizing handle or move frame selected, # set sizing mode and save current frame for its position if self.animation_data.active_frame is not None: for i in range(0, len(self.sizing_handles)): if self.sizing_handles[i].contains(mouse.pos()): self.sizing_mode = SizingMode(i) self.original_frame_positions = [self.animation_data.active_frame.translated(0, 0)] return if self.animation_data.active_frame.contains(mouse_rel): self.sizing_mode = SizingMode.MOVE_FRAME self.original_frame_positions = [] for frame in self.animation_data.selected_frames(): self.original_frame_positions.append(frame.translated(0, 0)) return # If another frame was selected, set as active frame. key_mods = QtGui.QGuiApplication.queryKeyboardModifiers() frame = self.animation_data.active_sequence.frame_at_pos(mouse_rel) if self.animation_data.active_sequence is None: print("No active sequence") if frame is None: self.animation_data.active_sequence.selected = [] self.animation_data.active_frame = None else: if key_mods == Qt.ControlModifier: # Select an additional frame self.animation_data.active_sequence.select(frame) elif key_mods == Qt.ShiftModifier: # Select a range of frames index_a = self.animation_data.active_sequence.active_frame_index() index_b = self.animation_data.active_sequence.frame_index(frame) if index_a > index_b: index_a, index_b = index_b, index_a for i in range(index_a, index_b + 1): self.animation_data.active_sequence.select(self.animation_data.active_sequence.frames[i]) else: # Clear selection and add new frame self.animation_data.active_sequence.set_sole(frame) self.animation_data.active_frame = frame #if key_mods self.animation_data_changed_signal.emit() # Click once to select, click once again to move frame self.left_mouse_down = False self.update() if self.mode == ViewerMode.NEW_FRAME: # If no active sequence, createa a new one if self.animation_data.active_sequence is None: self.animation_data.new_sequence(active=True) logging.info("New sequence created") # Create a new frame cord = self.view2sheet(mouse.pos()) self.animation_data.active_sequence.add_frame(AnimationFrame(cord)) self.animation_data_changed_signal.emit() logging.info("New frame created at X:%s Y:%s" % (cord.x(), cord.y())) # Zooming in / out with zoom tool if self.mode == ViewerMode.ZOOM: if mouse.button() == Qt.LeftButton: self.setCursor(self.zoom_in_cursor) elif mouse.button() == Qt.RightButton: self.setCursor(self.zoom_out_cursor) def mouseReleaseEvent(self, mouse): if self.animation_data is None: return if mouse.button() == Qt.MidButton or mouse.button() == Qt.RightButton: self.isPanning = False self.reset_cursor() # Zooming in / out with zoom tool if self.mode == ViewerMode.ZOOM: if mouse.button() == Qt.LeftButton: self.zoom_in() self.reset_cursor() elif mouse.button() == Qt.RightButton: self.zoom_out() self.reset_cursor() if mouse.button() == Qt.LeftButton: self.left_mouse_down = False if (self.mode == ViewerMode.ALTER_SELECTION or self.mode == ViewerMode.NEW_FRAME) and self.animation_data.active_frame is not None: self.sizing_mode = None self.animation_data.active_frame.normalize() frame_start = self.view2sheet(self.mouse_press_pos) frame_end = self.view2sheet(mouse) self.update() #Delete active frame if size is zero if self.animation_data.active_frame is not None: frame = self.animation_data.active_frame if frame.width() == 0 or frame.height() == 0: del self.animation_data.active_frame self.animation_data_changed_signal.emit() def mouseMoveEvent(self, mouse): self.last_mouse_pos = mouse.pos() if self.isPanning: # Move spritesheet frame according to mouse displacement mouse_pos_change = (mouse.pos() - self.mouse_press_pos) / self.scale self.camera = self.camera_old - mouse_pos_change self.constrain_camera() self.calc_sizing_handles() # Creating a new frame if self.mode == ViewerMode.NEW_FRAME: if self.left_mouse_down: # Adjust size of new frame selection clicked_pos = self.view2sheet(self.mouse_press_pos) mouse_pos = self.view2sheet(mouse.pos()) frame = self.animation_data.active_frame frame.setTopLeft(clicked_pos) frame.setBottomRight(QPoint(mouse_pos.x()-1, mouse_pos.y()-1)) self.animation_data_changed_signal.emit() # Altering an existing frame elif self.mode == ViewerMode.ALTER_SELECTION: if self.animation_data.active_frame is not None and self.animation_data.active_frame in self.animation_data.active_sequence.selected: a_frame = self.animation_data.active_frame mouse_rel = self.view2sheet(mouse.pos()) if self.sizing_mode is None: # self.sizing_handles -> contains 8 rects self.setCursor(Qt.ArrowCursor) if a_frame.contains(mouse_rel): self.setCursor(self.move_frame_cursor) for i in range(0, len(self.sizing_handles)): if self.sizing_handles[i].contains(mouse.pos()): self.setCursor(self.sizing_handle_cursors[i]) elif self.left_mouse_down: # Position = original + (mouse_click_pos - mouse_current_pos) delta_mouse = self.view2sheet(self.mouse_press_pos) - self.view2sheet(mouse.pos()) if self.sizing_mode is SizingMode.MOVE_FRAME: selected_frames = self.animation_data.selected_frames() i = 0 for frame in self.original_frame_positions: selected_frames[i].moveTo(frame.topLeft() - delta_mouse) i += 1 elif self.sizing_mode is SizingMode.TOP_LEFT: a_frame.setTopLeft(self.original_frame.topLeft() - delta_mouse) elif self.sizing_mode is SizingMode.TOP: a_frame.setTop(self.original_frame.top() - delta_mouse.y()) elif self.sizing_mode is SizingMode.TOP_RIGHT: a_frame.setTopRight(self.original_frame.topRight() - delta_mouse) elif self.sizing_mode is SizingMode.RIGHT: a_frame.setRight(self.original_frame.right() - delta_mouse.x()) elif self.sizing_mode is SizingMode.BOTTOM_RIGHT: a_frame.setBottomRight(self.original_frame.bottomRight() - delta_mouse) elif self.sizing_mode is SizingMode.BOTTOM: a_frame.setBottom(self.original_frame.bottom() - delta_mouse.y()) elif self.sizing_mode is SizingMode.BOTTOM_LEFT: a_frame.setBottomLeft(self.original_frame.bottomLeft() - delta_mouse) elif self.sizing_mode is SizingMode.LEFT: a_frame.setLeft(self.original_frame.left() - delta_mouse.x()) self.animation_data_changed_signal.emit() self.calc_sizing_handles() self.update() def keyPressEvent(self, e: QtGui.QKeyEvent) -> None: print("keypress") a_frame = self.animation_data.active_frame self.setFocus() # Theres got to be a better way to do this modifiers = QtWidgets.QApplication.keyboardModifiers() if modifiers & Qt.ControlModifier: if e.key() == Qt.Key_Up: a_frame.shift.setY(a_frame.shift.y() - 1) if e.key() == Qt.Key_Down: a_frame.shift.setY(a_frame.shift.y() + 1) if e.key() == Qt.Key_Left: a_frame.shift.setX(a_frame.shift.x() - 1) if e.key() == Qt.Key_Right: a_frame.shift.setX(a_frame.shift.x() + 1) else: # Move all frames selected for sequence in self.animation_data.selected: for frame in sequence.selected: if e.key() == Qt.Key_Up: frame.translate( 0, -1 ) elif e.key() == Qt.Key_Down: frame.translate(0, 1) elif e.key() == Qt.Key_Left: frame.translate(-1, 0) elif e.key() == Qt.Key_Right: frame.translate(1, 0) elif e.key() == Qt.Key_F: self.focus_selected() self.calc_sizing_handles() self.update() self.animation_data_changed_signal.emit() def enterEvent(self, event): self.update() def leaveEvent(self, event): self.update() def reset_cursor(self): if self.mode == ViewerMode.NEW_FRAME: self.setCursor(Qt.BlankCursor) elif self.mode == ViewerMode.ALTER_SELECTION: self.setCursor(Qt.ArrowCursor) elif self.mode == ViewerMode.ZOOM: self.setCursor(self.zoom_cursor) else: self.setCursor(Qt.ArrowCursor) def view2sheet(self, cord): #Get mouse position relative to the spritesheet return QPoint(math.floor(cord.x() / self.scale) + self.camera.x(), math.floor(cord.y() / self.scale) + self.camera.y()) def sheet2view(self, cord): #Get spritesheet position relative to mouse position return QPoint(math.floor((cord.x() - self.camera.x()) * self.scale), math.floor((cord.y() - self.camera.y()) * self.scale))
class GLWidget(QOpenGLWidget): def __init__(self, parent=None): super(GLWidget, self).__init__(parent) midnight = QTime(0, 0, 0) random.seed(midnight.secsTo(QTime.currentTime())) self.object = 0 self.xRot = 0 self.yRot = 0 self.zRot = 0 self.image = QImage() self.bubbles = [] self.lastPos = QPoint() self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0) self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0) self.animationTimer = QTimer() self.animationTimer.setSingleShot(False) self.animationTimer.timeout.connect(self.animate) self.animationTimer.start(25) self.setAutoFillBackground(False) self.setMinimumSize(200, 200) self.setWindowTitle("Overpainting a Scene") def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle def setZRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.zRot: self.zRot = angle def initializeGL(self): # gl = self.context().versionFunctions() # gl.initializeOpenGLFunctions() self.object = self.makeObject() def mousePressEvent(self, event): self.lastPos = event.pos() def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.setXRotation(self.xRot + 8 * dy) self.setYRotation(self.yRot + 8 * dx) elif event.buttons() & Qt.RightButton: self.setXRotation(self.xRot + 8 * dy) self.setZRotation(self.zRot + 8 * dx) self.lastPos = event.pos() def paintEvent(self, event): self.makeCurrent() gl.glMatrixMode(gl.GL_MODELVIEW) gl.glPushMatrix() self.setClearColor(self.trolltechPurple.darker()) gl.glShadeModel(gl.GL_SMOOTH) gl.glEnable(gl.GL_DEPTH_TEST) #gl.glEnable(gl.GL_CULL_FACE) gl.glEnable(gl.GL_LIGHTING) gl.glEnable(gl.GL_LIGHT0) gl.glEnable(gl.GL_MULTISAMPLE) gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, (0.5, 5.0, 7.0, 1.0)) self.setupViewport(self.width(), self.height()) gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) gl.glLoadIdentity() gl.glTranslated(0.0, 0.0, -10.0) gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0) gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0) gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0) gl.glCallList(self.object) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glPopMatrix() painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) for bubble in self.bubbles: if bubble.rect().intersects(QRectF(event.rect())): bubble.drawBubble(painter) self.drawInstructions(painter) painter.end() def resizeGL(self, width, height): self.setupViewport(width, height) def showEvent(self, event): self.createBubbles(20 - len(self.bubbles)) def sizeHint(self): return QSize(400, 400) def makeObject(self): genList = gl.glGenLists(1) gl.glNewList(genList, gl.GL_COMPILE) gl.glBegin(gl.GL_QUADS) x1 = +0.06 y1 = -0.14 x2 = +0.14 y2 = -0.06 x3 = +0.08 y3 = +0.00 x4 = +0.30 y4 = +0.22 self.quad(x1, y1, x2, y2, y2, x2, y1, x1) self.quad(x3, y3, x4, y4, y4, x4, y3, x3) self.extrude(x1, y1, x2, y2) self.extrude(x2, y2, y2, x2) self.extrude(y2, x2, y1, x1) self.extrude(y1, x1, x1, y1) self.extrude(x3, y3, x4, y4) self.extrude(x4, y4, y4, x4) self.extrude(y4, x4, y3, x3) NumSectors = 200 for i in range(NumSectors): angle1 = (i * 2 * math.pi) / NumSectors x5 = 0.30 * math.sin(angle1) y5 = 0.30 * math.cos(angle1) x6 = 0.20 * math.sin(angle1) y6 = 0.20 * math.cos(angle1) angle2 = ((i + 1) * 2 * math.pi) / NumSectors x7 = 0.20 * math.sin(angle2) y7 = 0.20 * math.cos(angle2) x8 = 0.30 * math.sin(angle2) y8 = 0.30 * math.cos(angle2) self.quad(x5, y5, x6, y6, x7, y7, x8, y8) self.extrude(x6, y6, x7, y7) self.extrude(x8, y8, x5, y5) gl.glEnd() gl.glEndList() return genList def quad(self, x1, y1, x2, y2, x3, y3, x4, y4): gl.glNormal3d(0.0, 0.0, -1.0) gl.glVertex3d(x1, y1, -0.05) gl.glVertex3d(x2, y2, -0.05) gl.glVertex3d(x3, y3, -0.05) gl.glVertex3d(x4, y4, -0.05) gl.glNormal3d(0.0, 0.0, 1.0) gl.glVertex3d(x4, y4, +0.05) gl.glVertex3d(x3, y3, +0.05) gl.glVertex3d(x2, y2, +0.05) gl.glVertex3d(x1, y1, +0.05) def extrude(self, x1, y1, x2, y2): self.setColor(self.trolltechGreen.darker(250 + int(100 * x1))) gl.glNormal3d((x1 + x2) / 2.0, (y1 + y2) / 2.0, 0.0) gl.glVertex3d(x1, y1, +0.05) gl.glVertex3d(x2, y2, +0.05) gl.glVertex3d(x2, y2, -0.05) gl.glVertex3d(x1, y1, -0.05) def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle def createBubbles(self, number): for i in range(number): position = QPointF(self.width() * (0.1 + 0.8 * random.random()), self.height() * (0.1 + 0.8 * random.random())) radius = min(self.width(), self.height()) * (0.0125 + 0.0875 * random.random()) velocity = QPointF( self.width() * 0.0125 * (-0.5 + random.random()), self.height() * 0.0125 * (-0.5 + random.random())) self.bubbles.append(Bubble(position, radius, velocity)) def animate(self): for bubble in self.bubbles: bubble.move(self.rect()) self.update() def setupViewport(self, width, height): side = min(width, height) gl.glViewport((width - side) // 2, (height - side) // 2, side, side) gl.glMatrixMode(gl.GL_PROJECTION) gl.glLoadIdentity() gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0) gl.glMatrixMode(gl.GL_MODELVIEW) def drawInstructions(self, painter): text = "Click and drag with the left mouse button to rotate the Qt " \ "logo." metrics = QFontMetrics(self.font()) border = max(4, metrics.leading()) rect = metrics.boundingRect(0, 0, self.width() - 2 * border, int(self.height() * 0.125), Qt.AlignCenter | Qt.TextWordWrap, text) painter.setRenderHint(QPainter.TextAntialiasing) painter.fillRect(QRect(0, 0, self.width(), rect.height() + 2 * border), QColor(0, 0, 0, 127)) painter.setPen(Qt.white) painter.fillRect(QRect(0, 0, self.width(), rect.height() + 2 * border), QColor(0, 0, 0, 127)) painter.drawText( (self.width() - rect.width()) / 2, border, rect.width(), rect.height(), Qt.AlignCenter | Qt.TextWordWrap, text) def setClearColor(self, c): gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()) def setColor(self, c): gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
class Example(QWidget): overlay: QImage #Overlay(Накладываем) Picture on Window timer: QTimer #Timet init painter: QPainter Colors: list arr_points: list DeltaX: int DeltaY: int SelfHeight: int LastAngle: int stationSize: list LastMousePosition: QPoint AllData: pd.DataFrame #WithDates: pd.DataFrame toolTipWidget: QLabel pytrends: TrendReq def __init__(self): super().__init__() self.initUI() def keyPressEvent(self, event): if event.key() == 16777216: #Esc #self.FileSaving(self.arr_points, FILE_NAME) sys.exit() #Programm Closing elif event.key() == 16777249: #Ctrl self.UpdateGoogleData() #self.FileSaving(self.GetGoogleData(stationsName), FILE_DATA_NAME) def UpdateGoogleData(self): self.pytrends = TrendReq(hl='ru-RU', tz=360) for i, row in self.AllData.iterrows(): if not row['popularity_mean'] > 0 or IS_FULL_LOAD: station_popularity_mean, station_popularity = self.GetStation_popularity( row['Name'], self.pytrends) print(row['Name'] + ' ' + str(round(station_popularity_mean, 2))) self.AllData.at[i, 'popularity_mean'] = station_popularity_mean self.AllData.at[i, 'popularity'] = ':'.join(station_popularity) else: print(row['Name'] + ' ' + str(round(row['popularity_mean'], 2)) + ' old') # self.FileDrawing(False) QApplication.processEvents() # if i>10: # break #self.WithDates.to_csv(FILE_DATES_NAME, index = False, sep=',', encoding='utf-8-sig') if i % 10 == 0: self.AllData.to_csv(FILE_DATA_NAME, index=False, sep=',', encoding='utf-8-sig') print('All Loaded!') def GetStation_popularity(self, station_name, trends_object): # station_name = 'Тульская' # timeframe='today 5-y' suggestions_dict = self.pytrends.suggestions(keyword=station_name + ' Станция метрополитена') # kw_list = station_name 'type:Moscow Metro'] suggestions = [ x for x in suggestions_dict if x['title'] == station_name ] if len(suggestions) > 0: kw_list = [suggestions[0]['mid']] print(' ' + suggestions[0]['type']) else: return 0 # kw_list = [station_name] trends_object.build_payload(kw_list, cat=0, geo='RU', timeframe='2017-01-01 2018-11-01', gprop='') interest = trends_object.interest_over_time() #print(interest) #self.WithDates.set_index('date') #self.WithDates = self.WithDates.append(interest) print(interest) print(list(interest.columns.values)) mean = interest.mean() if len(list(mean)) > 0: return mean[0], interest['/m/06v6qd'] else: return 0 def mousePressEvent(self, event): mousePoint = event.pos() self.LastMousePosition = mousePoint if event.button() == 1: # self.painter.setFont(QFont('Arial', 111)) # self.painter.drawText(QPoint(200,200), 'HELLO') WindowW = self.frameGeometry().width() # WindowSize WindowH = self.frameGeometry().height() # WindowSize imgH = self.overlay.height() # Original Picture Size imgW = self.overlay.width() # Original Picture Size img = self.overlay.scaledToHeight(self.SelfHeight, Qt.FastTransformation) #AdjX = (WindowW-img.width())/2 ResultX = imgW * (mousePoint.x() - self.DeltaX) / img.width() ResultY = imgH / 100 * ((mousePoint.y() - self.DeltaY) / (self.SelfHeight / 100)) #eraser = 7 #self.painter.drawEllipse(QPoint(ResultX, ResultY), RADIUS, RADIUS) for i, row in self.AllData.iterrows(): if ResultX >= row['X'] - (row['popularity_mean'] + ADDITIONAL) /2 and \ ResultX <= row['X'] + (row['popularity_mean'] + ADDITIONAL) /2 and \ ResultY >= row['Y'] - (row['popularity_mean'] + ADDITIONAL) /2 and \ ResultY <= row['Y'] + (row['popularity_mean'] + ADDITIONAL) /2: text = row['Name'] + ', ' + str( round(row['popularity_mean'], 1)) + '%' self.toolTipWidget.setText(text) self.toolTipWidget.move(event.pos()) self.toolTipWidget.adjustSize() self.toolTipWidget.show() #self.painter.eraseRect(QRect(QPoint(ResultX-RADIUS/2-eraser, ResultY-RADIUS/2-eraser), QPoint(ResultX+radius/2+eraser, ResultY+radius/2+eraser))) self.arr_points.append((ResultX, ResultY)) #print([(round(x[0]), round(x[1])) for x in self.arr_points]) self.update() #Redraw if event.button() == 2: WindowW = self.frameGeometry().width() # WindowSize WindowH = self.frameGeometry().height() # WindowSize imgH = self.overlay.height() # Original Picture Size imgW = self.overlay.width() # Original Picture Size img = self.overlay.scaledToHeight(self.SelfHeight, Qt.FastTransformation) #AdjX = (WindowW-img.width())/2 ResultX = imgW * (mousePoint.x() - self.DeltaX) / img.width() ResultY = imgH / 100 * ((mousePoint.y() - self.DeltaY) / (self.SelfHeight / 100)) #eraser = 7 self.painter.drawEllipse(QPoint(ResultX, ResultY), RADIUS, RADIUS) #self.painter.eraseRect(QRect(QPoint(ResultX-RADIUS/2-eraser, ResultY-RADIUS/2-eraser), QPoint(ResultX+radius/2+eraser, ResultY+radius/2+eraser))) self.arr_points.append((ResultX, ResultY)) #print([(round(x[0]), round(x[1])) for x in self.arr_points]) self.update() #Redraw def mouseReleaseEvent(self, event): self.point = None self.toolTipWidget.hide() ''' def FileSaving(self, arr: list, fileName: str): with open(fileName, 'w') as f: for item in arr: f.write(','.join(str(x) for x in item) + '\n') f.close() def FileReading(self, fileName: str): with open(fileName, 'r') as f: names = f.read().split('\n') f.close() #print(names) return [x.split(',') for x in names] def GetGoogleData(self, namesSt: list): stationSizes = [] for station in namesSt: sz = self.GetStationpopularity_meanarity([station], self.pytrends) if sz>0: stationSizes.append([station, sz]) print(station+': '+str(round(sz, 1))) else: print(station+' error') return stationSizes ''' def FileDrawing(self, animate): if not animate: self.timer.stop() penLine = QPen(QColor(Qt.red)) penLine.setWidth(10) for i, row in self.AllData.iterrows(): penEllipse = QPen(self.Colors[int(row['Line'].replace('A', '')) - 1]) penEllipse.setWidth(5) x = row['X'] y = row['Y'] # self.AllData[allDataI].append(x) #self.AllData[allDataI].append(y) #if lastX is not None or lastY is not None: self.painter.setPen(penLine) #Point1 = QPoint(lastX, lastY) #Point2 = QPoint(float(x), float(y)) #self.painter.drawLine(Point1, Point2) self.painter.setPen(penEllipse) penLine = QPen(QColor(Qt.red)) self.painter.setBrush(QColor(Qt.white)) if row['popularity_mean'] > 0: CircleSize = (RADIUS / 100) * row['popularity_mean'] + ADDITIONAL else: CircleSize = 10 #print(CircleSize) #if n == 8 and i>=11 and i<=12: self.painter.drawEllipse( float(x) - CircleSize, float(y) - CircleSize, CircleSize * 2, CircleSize * 2) QApplication.processEvents() #sleep(1) self.timer.start(1000 / UPDATE_SPEED) self.overlay.save('Picture Of Map.jpg', format='jpeg') def closeEvent(self, event): #self.FileSaving(self.arr_points, FILE_NAME) sys.exit() #Programm Closing def initUI(self): self.Colors = [ QColor(228, 37, 24), #1 QColor(75, 175, 79), #2 QColor(5, 114, 185), #3 QColor(36, 188, 239), #4 QColor(146, 82, 51), #5 QColor(239, 128, 39), #6 QColor(148, 63, 144), #7 QColor(255, 209, 30), #8 QColor(173, 172, 172), #9 QColor(185, 206, 31), #10 QColor(134, 204, 206), #11 QColor(186, 200, 232), #12 QColor(68, 143, 201), #13 QColor(232, 68, 57), #14 ] self.showMaximized() #self.showNormal() self.setStyleSheet("background-color: white;") self.toolTipWidget = QLabel() self.toolTipWidget.setStyleSheet("QLabel {" "border-style: solid;" "border-width: 1px;" "border-color: grey; " "border-radius: 3px;" "padding: 5px 5px 5px 5px;" "background-color: rgb(255,255,225);" "}") self.toolTipWidget.setWindowFlags(Qt.ToolTip) self.toolTipWidget.setAttribute(Qt.WA_TransparentForMouseEvents) self.toolTipWidget.hide() self.interest = None self.arr_points = [] self.stationSize = [] self.LastAngle = 0 self.timer = QTimer() #Timer init self.timer.timeout.connect(self.update) # Timer init self.setWindowTitle('Moscow Metro Map Poppularity') # Title self.point = None self.DeltaX = 0 self.DeltaY = 0 self.SelfHeight = self.frameGeometry().height() self.LastMousePosition = QPoint(0, 0) self.overlay = QImage() #self.overlay.load('Moscow Metro Map Stations popularity_meanarity\\MainMap.bmp') self.overlay.load(FILE_BACKGROUND) pen = QPen(QColor(Qt.red)) pen.setWidth(5) self.painter = QPainter(self.overlay) self.painter.setPen(pen) self.painter.Antialiasing = False self.timer.start(1000 / UPDATE_SPEED) #self.AllData = self.FileReading(FILE_DATA_NAME) self.AllData = pd.read_csv(FILE_DATA_NAME, ',', encoding='utf-8-sig') #self.WithDates = pd.read_csv(FILE_DATES_NAME,',', encoding='utf-8-sig') #print(self.WithDates) # self.AllData = [x for x in self.AllData.iterrows() if x['Line']='8A'] #self.arr_points = self.FileReading() # self.FileDrawing() def paintEvent(self, event): painter = QPainter() painter.begin(self) #windowsWidth = self.frameGeometry().width() windowsHeight = self.frameGeometry().height() img = self.overlay.scaledToHeight(self.SelfHeight, 0) painter.drawImage(self.DeltaX, self.DeltaY, img) painter.end() del painter def mouseMoveEvent(self, event): CurentPos = event.pos() self.DeltaX -= self.LastMousePosition.x() - CurentPos.x() self.DeltaY -= self.LastMousePosition.y() - CurentPos.y() #self.LastMousePosition = mousePoint self.LastMousePosition = event.pos() def wheelEvent(self, event): #print(str(event.angleDelta())) self.SelfHeight += (event.angleDelta().y()) / 10 self.LastAngle = event.angleDelta().y() def resizeEvent(self, event): self.SelfHeight = self.frameGeometry().height() - 10 if hasattr(self, 'overlay'): img = self.overlay.scaledToHeight(self.SelfHeight, 0) self.DeltaX = (self.frameGeometry().width() - img.width()) / 2 self.DeltaY = 0
class MandelbrotWidget(QWidget): def __init__(self, parent=None): super(MandelbrotWidget, self).__init__(parent) self.thread = RenderThread() self.pixmap = QPixmap() self.pixmapOffset = QPoint() self.lastDragPos = QPoint() self.centerX = DefaultCenterX self.centerY = DefaultCenterY self.pixmapScale = DefaultScale self.curScale = DefaultScale self.thread.renderedImage.connect(self.updatePixmap) self.setWindowTitle("Mandelbrot") self.setCursor(Qt.CrossCursor) self.resize(550, 400) def paintEvent(self, event): painter = QPainter(self) painter.fillRect(self.rect(), Qt.black) if self.pixmap.isNull(): painter.setPen(Qt.white) painter.drawText(self.rect(), Qt.AlignCenter, "Rendering initial image, please wait...") return if self.curScale == self.pixmapScale: painter.drawPixmap(self.pixmapOffset, self.pixmap) else: scaleFactor = self.pixmapScale / self.curScale newWidth = int(self.pixmap.width() * scaleFactor) newHeight = int(self.pixmap.height() * scaleFactor) newX = self.pixmapOffset.x() + (self.pixmap.width() - newWidth) / 2 newY = self.pixmapOffset.y() + (self.pixmap.height() - newHeight) / 2 painter.save() painter.translate(newX, newY) painter.scale(scaleFactor, scaleFactor) exposed, _ = painter.worldTransform().inverted() exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1) painter.drawPixmap(exposed, self.pixmap, exposed) painter.restore() text = "Use mouse wheel or the '+' and '-' keys to zoom. Press and " \ "hold left mouse button to scroll." metrics = painter.fontMetrics() textWidth = metrics.width(text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(0, 0, 0, 127)) painter.drawRect((self.width() - textWidth) / 2 - 5, 0, textWidth + 10, metrics.lineSpacing() + 5) painter.setPen(Qt.white) painter.drawText((self.width() - textWidth) / 2, metrics.leading() + metrics.ascent(), text) def resizeEvent(self, event): self.thread.render(self.centerX, self.centerY, self.curScale, self.size()) def keyPressEvent(self, event): if event.key() == Qt.Key_Plus: self.zoom(ZoomInFactor) elif event.key() == Qt.Key_Minus: self.zoom(ZoomOutFactor) elif event.key() == Qt.Key_Left: self.scroll(-ScrollStep, 0) elif event.key() == Qt.Key_Right: self.scroll(+ScrollStep, 0) elif event.key() == Qt.Key_Down: self.scroll(0, -ScrollStep) elif event.key() == Qt.Key_Up: self.scroll(0, +ScrollStep) else: super(MandelbrotWidget, self).keyPressEvent(event) def wheelEvent(self, event): numDegrees = event.angleDelta().y() / 8 numSteps = numDegrees / 15.0 self.zoom(pow(ZoomInFactor, numSteps)) def mousePressEvent(self, event): if event.buttons() == Qt.LeftButton: self.lastDragPos = QPoint(event.pos()) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.pixmapOffset += event.pos() - self.lastDragPos self.lastDragPos = QPoint(event.pos()) self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.pixmapOffset += event.pos() - self.lastDragPos self.lastDragPos = QPoint() deltaX = (self.width() - self.pixmap.width()) / 2 - self.pixmapOffset.x() deltaY = (self.height() - self.pixmap.height()) / 2 - self.pixmapOffset.y() self.scroll(deltaX, deltaY) def updatePixmap(self, image, scaleFactor): if not self.lastDragPos.isNull(): return self.pixmap = QPixmap.fromImage(image) self.pixmapOffset = QPoint() self.lastDragPosition = QPoint() self.pixmapScale = scaleFactor self.update() def zoom(self, zoomFactor): self.curScale *= zoomFactor self.update() self.thread.render(self.centerX, self.centerY, self.curScale, self.size()) def scroll(self, deltaX, deltaY): self.centerX += deltaX * self.curScale self.centerY += deltaY * self.curScale self.update() self.thread.render(self.centerX, self.centerY, self.curScale, self.size())
def createCurveIcons(self): pix = QPixmap(self.m_iconSize) painter = QPainter() gradient = QLinearGradient(0, 0, 0, self.m_iconSize.height()) gradient.setColorAt(0.0, QColor(240, 240, 240)) gradient.setColorAt(1.0, QColor(224, 224, 224)) brush = QBrush(gradient) # The original C++ code uses undocumented calls to get the names of the # different curve types. We do the Python equivalant (but without # cheating). curve_types = [ (n, c) for n, c in QEasingCurve.__dict__.items() if isinstance(c, QEasingCurve.Type) and c != QEasingCurve.Custom ] curve_types.sort(key=lambda ct: ct[1]) painter.begin(pix) for curve_name, curve_type in curve_types: painter.fillRect(QRect(QPoint(0, 0), self.m_iconSize), brush) curve = QEasingCurve(curve_type) if curve_type == QEasingCurve.BezierSpline: curve.addCubicBezierSegment(QPointF(0.4, 0.1), QPointF(0.6, 0.9), QPointF(1.0, 1.0)) elif curve_type == QEasingCurve.TCBSpline: curve.addTCBSegment(QPointF(0.0, 0.0), 0, 0, 0) curve.addTCBSegment(QPointF(0.3, 0.4), 0.2, 1, -0.2) curve.addTCBSegment(QPointF(0.7, 0.6), -0.2, 1, 0.2) curve.addTCBSegment(QPointF(1.0, 1.0), 0, 0, 0) painter.setPen(QColor(0, 0, 255, 64)) xAxis = self.m_iconSize.height() / 1.5 yAxis = self.m_iconSize.width() / 3.0 painter.drawLine(0, xAxis, self.m_iconSize.width(), xAxis) painter.drawLine(yAxis, 0, yAxis, self.m_iconSize.height()) curveScale = self.m_iconSize.height() / 2.0 painter.setPen(Qt.NoPen) # Start point. painter.setBrush(Qt.red) start = QPoint(yAxis, xAxis - curveScale * curve.valueForProgress(0)) painter.drawRect(start.x() - 1, start.y() - 1, 3, 3) # End point. painter.setBrush(Qt.blue) end = QPoint(yAxis + curveScale, xAxis - curveScale * curve.valueForProgress(1)) painter.drawRect(end.x() - 1, end.y() - 1, 3, 3) curvePath = QPainterPath() curvePath.moveTo(QPointF(start)) t = 0.0 while t <= 1.0: to = QPointF(yAxis + curveScale * t, xAxis - curveScale * curve.valueForProgress(t)) curvePath.lineTo(to) t += 1.0 / curveScale painter.setRenderHint(QPainter.Antialiasing, True) painter.strokePath(curvePath, QColor(32, 32, 32)) painter.setRenderHint(QPainter.Antialiasing, False) item = QListWidgetItem() item.setIcon(QIcon(pix)) item.setText(curve_name) self.m_ui.easingCurvePicker.addItem(item) painter.end()
class ImageArea(QWidget): def __init__(self, width, height): super(ImageArea, self).__init__() self.imgPixmap = None self.scaledImg = None self.img_offset = QPoint(0, 0) # initialize offset self.isLeftPressed = bool(False) self.isImgLabelArea = bool(True) # mouse into the area of image self.layout_width = width # the width of the windows can display image self.layout_height = height # the height of the windows can display image self.select_mode = False # select image by user self.select_rect = QRect(0, 0, 0, 0) # the info of select area self.select_begin_point = QPoint(0, 0) # for show the info of the image self.lblTest = QtWidgets.QLabel(self) self.lblTest.setGeometry(10, 550, 300, 20) self.lblTest.setText("Offset: (0, 0)") def update_image(self, pixmap): self.imgPixmap = pixmap self.scaledImg = self.imgPixmap.copy() self.img_offset = QPoint(0, 0) self.update() # repaint the image def paintEvent(self, event): self.imgPainter = QPainter() # display image self.imgPainter.begin(self) self.lblTest.setText("Offset: ({0}, {1})".format( self.img_offset.x(), self.img_offset.y())) if self.scaledImg is not None: self.imgPainter.drawPixmap( self.img_offset, self.scaledImg) # display image with offset if self.select_mode: # display select frame self.rectPainter = QPainter() self.rectPainter.begin(self) self.rectPainter.setPen(QPen(Qt.red, 2, Qt.DashLine)) self.rectPainter.drawRect(self.select_rect) self.rectPainter.end() self.imgPainter.end() def mousePressEvent(self, event): if event.buttons() == QtCore.Qt.LeftButton: print("Click left mouse") self.isLeftPressed = True self.preMousePosition = event.pos( ) # get mouse position when click mouse if self.select_mode: self.select_begin_point = event.pos() def wheelEvent(self, event): angle = event.angleDelta() / 8 # QPoint() wheel scroll distance angle_x = angle.x() # horizontal scroll distance angle_y = angle.y() # vertical scroll distance if angle_y > 0: # scroll up print("Scroll up") self.scaledImg = self.imgPixmap.scaled( self.scaledImg.width() + self.imgPixmap.width() // 20, self.scaledImg.height() + self.imgPixmap.height() // 20, Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation ) # change the size of image # try to keep the mouse point to the same position after the size changed new_width = event.x() - (self.scaledImg.width() * (event.x() - self.img_offset.x())) \ / (self.scaledImg.width() - self.imgPixmap.width() // 20) new_height = event.y() - (self.scaledImg.height() * (event.y() - self.img_offset.y())) \ / (self.scaledImg.height() - self.imgPixmap.height() // 20) self.img_offset = QPoint(new_width, new_height) # update offset self.update() else: # scroll down print("Scroll down") self.scaledImg = self.imgPixmap.scaled( self.scaledImg.width() - self.imgPixmap.width() // 20, self.scaledImg.height() - self.imgPixmap.height() // 20, Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation ) # change the size of image # try to keep the mouse point to the same position after the size changed new_width = event.x() - (self.scaledImg.width() * (event.x() - self.img_offset.x())) \ / (self.scaledImg.width() + self.imgPixmap.width() // 20) new_height = event.y() - (self.scaledImg.height() * (event.y() - self.img_offset.y())) \ / (self.scaledImg.height() + self.imgPixmap.height() // 20) self.img_offset = QPoint(new_width, new_height) # update offset self.update() def mouseReleaseEvent(self, event): if event.buttons() == QtCore.Qt.LeftButton: self.isLeftPressed = False print("Release left mouse") elif event.button() == Qt.RightButton: self.img_offset = QPoint(0, 0) # reset the offset self.scaledImg = self.imgPixmap.scaled( self.imgPixmap.width(), self.imgPixmap.height(), Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) # 置为初值 self.update() print("Release right mouse") def mouseMoveEvent(self, event): if self.isLeftPressed: if self.select_mode: self.select_offset = event.pos( ) - self.select_begin_point # total offset of mouse when selecting self.select_rect = QRect(self.select_begin_point.x(), self.select_begin_point.y(), abs(self.select_offset.x()), abs(self.select_offset.y())) else: print("Click left mouse & move") width_gap = self.layout_width - self.scaledImg.width( ) # the gap between display window & image print(width_gap, self.layout_width, self.scaledImg.width()) height_gap = self.layout_height - self.scaledImg.height( ) # the gap between display window & image print(height_gap, self.layout_height, self.scaledImg.height()) once_offset = event.pos( ) - self.preMousePosition # the offset of this movement self.img_offset = self.img_offset + once_offset # update offset # if width of image smaller than width of layout if width_gap > 0: if self.img_offset.x() < 0: self.img_offset.setX(0) elif self.img_offset.x() > width_gap: self.img_offset.setX(width_gap) # if width of image bigger than width of layout else: if self.img_offset.x() > 0: self.img_offset.setX(0) elif self.img_offset.x() < width_gap: self.img_offset.setX(width_gap) # if height of image smaller than height of layout if height_gap > 0: if self.img_offset.y() < 0: self.img_offset.setY(0) elif self.img_offset.y() > height_gap: self.img_offset.setY(height_gap) # if height of image bigger than height of layout else: if self.img_offset.y() > 0: self.img_offset.setY(0) elif self.img_offset.y() < height_gap: self.img_offset.setY(height_gap) self.preMousePosition = event.pos( ) # update mouse position on the window self.update() def select_mode_change(self, is_select_mode): self.select_mode = is_select_mode
def _incline_line(self, path: QtGui.QPainterPath, point1: QtCore.QPoint, point2: QtCore.QPoint, span_left: list, span_right: list): #绘制站间的斜线 #TODO 暂未考虑直接跨过无定义区域的情况 width = self.graphWidget.scene.width() - \ self.graphWidget.margins["left"] - self.graphWidget.margins["right"] if point1.inRange and point2.inRange: if point1.x() <= point2.x(): path.lineTo(point2) else: # 跨界运行线 dx = point2.x() - point1.x() + width dy = point2.y() - point1.y() ax = width + self.graphWidget.margins["left"] - point1.x() h = ax * dy / dx span_right.append(point1.y() + h) span_left.append(point1.y() + h) path.lineTo(self.graphWidget.margins["left"] + width, point1.y() + h) path.moveTo(self.graphWidget.margins["left"], point1.y() + h) path.lineTo(point2) elif not point1.inRange and not point2.inRange: return elif point1.inRange: #右侧点越界 dx = point2.x() - point1.x() + width dy = point2.y() - point1.y() ax = width + self.graphWidget.margins["left"] - point1.x() h = ax * dy / dx span_right.append(point1.y() + h) path.lineTo(self.graphWidget.margins["left"] + width, point1.y() + h) else: #左侧点越界 dx = point2.x() - point1.x() + width dy = point2.y() - point1.y() ax = width + self.graphWidget.margins["left"] - point1.x() h = ax * dy / dx span_left.append(point1.y() + h) path.moveTo(self.graphWidget.margins["left"], point1.y() + h) path.lineTo(point2)
class HelloGLWidget(QOpenGLWidget): """HelloGLWidget(QOpenGLWidget) Provides a custom widget to display an OpenGL-rendered Qt logo. Various properties and slots are defined so that the user can rotate the logo, and signals are defined to enable other components to react to changes to its orientation. """ # We define three signals that are used to indicate changes to the # rotation of the logo. xRotationChanged = pyqtSignal(int) yRotationChanged = pyqtSignal(int) zRotationChanged = pyqtSignal(int) def __init__(self, parent=None): super(HelloGLWidget, self).__init__(parent) self.object = 0 self.xRot = 0 self.yRot = 0 self.zRot = 0 self.lastPos = QPoint() self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0) self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0) self.setWindowTitle("Hello GL") # The rotation of the logo about the x-axis can be controlled using the # xRotation property, defined using the following getter and setter # methods. def getXRotation(self): return self.xRot # The setXRotation() setter method is also a slot. @pyqtSlot(int) def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle self.xRotationChanged.emit(angle) self.update() xRotation = pyqtProperty(int, getXRotation, setXRotation) # The rotation of the logo about the y-axis can be controlled using the # yRotation property, defined using the following getter and setter # methods. def getYRotation(self): return self.yRot # The setYRotation() setter method is also a slot. @pyqtSlot(int) def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle self.yRotationChanged.emit(angle) self.update() yRotation = pyqtProperty(int, getYRotation, setYRotation) # The rotation of the logo about the z-axis can be controlled using the # zRotation property, defined using the following getter and setter # methods. def getZRotation(self): return self.zRot # The setZRotation() setter method is also a slot. @pyqtSlot(int) def setZRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.zRot: self.zRot = angle self.zRotationChanged.emit(angle) self.update() zRotation = pyqtProperty(int, getZRotation, setZRotation) def minimumSizeHint(self): return QSize(50, 50) def sizeHint(self): return QSize(200, 200) def initializeGL(self): self.gl = self.context().versionFunctions() self.gl.initializeOpenGLFunctions() self.setClearColor(self.trolltechPurple.darker()) self.object = self.makeObject() self.gl.glShadeModel(self.gl.GL_SMOOTH) self.gl.glEnable(self.gl.GL_DEPTH_TEST) self.gl.glEnable(self.gl.GL_CULL_FACE) def paintGL(self): self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT) self.gl.glLoadIdentity() self.gl.glTranslated(0.0, 0.0, -10.0) self.gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0) self.gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0) self.gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0) self.gl.glCallList(self.object) def resizeGL(self, width, height): side = min(width, height) self.gl.glViewport((width - side) / 2, (height - side) / 2, side, side) self.gl.glMatrixMode(self.gl.GL_PROJECTION) self.gl.glLoadIdentity() self.gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0) self.gl.glMatrixMode(self.gl.GL_MODELVIEW) def mousePressEvent(self, event): self.lastPos = QPoint(event.pos()) def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.setXRotation(self.xRot + 8 * dy) self.setYRotation(self.yRot + 8 * dx) elif event.buttons() & Qt.RightButton: self.setXRotation(self.xRot + 8 * dy) self.setZRotation(self.zRot + 8 * dx) self.lastPos = QPoint(event.pos()) def makeObject(self): genList = self.gl.glGenLists(1) self.gl.glNewList(genList, self.gl.GL_COMPILE) self.gl.glBegin(self.gl.GL_QUADS) x1 = +0.06 y1 = -0.14 x2 = +0.14 y2 = -0.06 x3 = +0.08 y3 = +0.00 x4 = +0.30 y4 = +0.22 self.quad(x1, y1, x2, y2, y2, x2, y1, x1) self.quad(x3, y3, x4, y4, y4, x4, y3, x3) self.extrude(x1, y1, x2, y2) self.extrude(x2, y2, y2, x2) self.extrude(y2, x2, y1, x1) self.extrude(y1, x1, x1, y1) self.extrude(x3, y3, x4, y4) self.extrude(x4, y4, y4, x4) self.extrude(y4, x4, y3, x3) Pi = 3.14159265358979323846 NumSectors = 200 for i in range(NumSectors): angle1 = (i * 2 * Pi) / NumSectors x5 = 0.30 * math.sin(angle1) y5 = 0.30 * math.cos(angle1) x6 = 0.20 * math.sin(angle1) y6 = 0.20 * math.cos(angle1) angle2 = ((i + 1) * 2 * Pi) / NumSectors x7 = 0.20 * math.sin(angle2) y7 = 0.20 * math.cos(angle2) x8 = 0.30 * math.sin(angle2) y8 = 0.30 * math.cos(angle2) self.quad(x5, y5, x6, y6, x7, y7, x8, y8) self.extrude(x6, y6, x7, y7) self.extrude(x8, y8, x5, y5) self.gl.glEnd() self.gl.glEndList() return genList def quad(self, x1, y1, x2, y2, x3, y3, x4, y4): self.setColor(self.trolltechGreen) self.gl.glVertex3d(x1, y1, -0.05) self.gl.glVertex3d(x2, y2, -0.05) self.gl.glVertex3d(x3, y3, -0.05) self.gl.glVertex3d(x4, y4, -0.05) self.gl.glVertex3d(x4, y4, +0.05) self.gl.glVertex3d(x3, y3, +0.05) self.gl.glVertex3d(x2, y2, +0.05) self.gl.glVertex3d(x1, y1, +0.05) def extrude(self, x1, y1, x2, y2): self.setColor(self.trolltechGreen.darker(250 + int(100 * x1))) self.gl.glVertex3d(x1, y1, +0.05) self.gl.glVertex3d(x2, y2, +0.05) self.gl.glVertex3d(x2, y2, -0.05) self.gl.glVertex3d(x1, y1, -0.05) def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle def setClearColor(self, c): self.gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()) def setColor(self, c): self.gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
def center_camera(self, point: QPoint) -> None: """ Centers the camera on a point on the spritesheet""" self.camera = QPoint(point.x() - self.width()/(2*self.scale), point.y() - self.height()/(2*self.scale)) self.constrain_camera()
class ObjectRotationManager: """ Allows a basic rotation system in the subclass QGLWidget In the subclass is mandatory to add as class parameters: xRotationChanged=pyqtSignal(int) yRotationChanged=pyqtSignal(int) zRotationChanged=pyqtSignal(int) """ def __init__(self): self.xRot = 0 self.yRot = 0 self.zRot = 0 self.lastPos = QPoint() def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle def xRotation(self): return self.xRot def yRotation(self): return self.yRot def zRotation(self): return self.zRot def mousePressEvent(self, event): self.lastPos = QPoint(event.pos()) def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.setXRotation(self.xRot + 8 * dy) self.setYRotation(self.yRot + 8 * dx) elif event.buttons() & Qt.RightButton: self.setXRotation(self.xRot + 8 * dy) self.setZRotation(self.zRot + 8 * dx) self.lastPos = QPoint(event.pos()) def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle self.xRotationChanged.emit(angle) self.updateGL() def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle self.yRotationChanged.emit(angle) self.updateGL() def setZRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.zRot: self.zRot = angle self.zRotationChanged.emit(angle) self.updateGL()
class Map: """ Map(width, height) """ def __init__(self, width=8, height=8): self.width = width self.height = height self.wall = [] # QPoint Type self.path = [] # QPoint Type self.rabbit = QPoint(0, 0) self.radish = QPoint(width - 1, height - 1) def set_map_size(self, width, height): self.width = width self.height = height def set_wall(self, position): """ The type of parameter:"position" is QPoint """ self.wall.append(position) def set_radish(self, position): self.radish = position def set_rabbit(self, position): self.rabbit = position def clear_one_wall(self, position): if not self.on_special_object("radish", position): if not self.on_special_object("rabbit", position): if self.on_special_object("wall", position): wall_index = self.wall.index(position) self.wall.pop(wall_index) def clear_all_wall(self): self.wall.clear() def on_special_object(self, spe_object, position): """ To judge whether the selected position is on the special object :param spe_object: "wall", "radish", "rabbit" :param position: QPoint type :return: True or False """ if spe_object == "wall": for i in range(len(self.wall)): if self.wall[i] == position: return True return False elif spe_object == "radish": if self.radish == position: return True else: return False elif spe_object == "rabbit": if self.radish == position: return True else: return False def out_map(self, position): if position.x() < 0 or position.x() > self.width - 1 or \ position.y() < 0 or position.y() > self.height - 1: return True else: return False def is_valid(self, position): """ when the point is not in the wall or out of the map, it is valid. :param position: QPoint Type position :return: True or False """ if self.out_map(position) or \ self.on_special_object("wall", position): return False else: return True def manhattan_length(self, pos1, pos2): """ compute the manhattan distance between pos1 and pos2 """ distance = pos1-pos2 return distance.manhattanLength() def a_star_searching(self): """ Use A* algorithm to find the best path between rabbit and radish :return: """ # time.clock() to compute the running time of a_star_searching if self.rabbit == QPoint(-1,-1) or self.radish == QPoint(-1,-1): return [False] start_time = time.clock() self.path.clear() open_list, close_list = [], [] # temp_point 在生成open表时有用,current_point表示目前搜索到的点 temp_point, current_point = QPoint(), QPoint() path_length = [[0 for i in range(self.height)] for j in range(self.width)] parent_point = [[QPoint(-1, -1) for i in range(self.height)] for j in range(self.width)] min_cost, temp_cost, sequence= 0, 0, 0 close_list.append(self.rabbit) while True: open_list.clear() # find the adjacent points of every point in close_list for i in range(len(close_list)): current_point = close_list[i] # temp_point is the adjacent points(4) of current_point temp_point = [copy.deepcopy(current_point) for i in range(4)] temp_point[0].setX(temp_point[0].x()-1) temp_point[1].setX(temp_point[1].x()+1) temp_point[2].setY(temp_point[2].y()-1) temp_point[3].setY(temp_point[3].y()+1) for j in range(4): if close_list.count(temp_point[j]) == 0 : if open_list.count(temp_point[j]) == 0: if self.is_valid(temp_point[j]): # use deepcopy to assure the open_list unchangeable when # the temp_point changes open_list.append(copy.deepcopy(temp_point[j])) if len(open_list) == 0: return [False] # find all the distance of between points in open_list and beginning point for i in range(len(open_list)): current_point = open_list[i] # makes the min_cost as large as possible min_cost = self.width * self.height for j in range(len(close_list)): temp_point = close_list[j] if self.manhattan_length(current_point, temp_point) == 1: temp_cost = path_length[temp_point.x()][temp_point.y()] + 1 if temp_cost < min_cost: min_cost = copy.deepcopy(temp_cost) sequence = j parent_point[current_point.x()][current_point.y()] = copy.deepcopy(close_list[sequence]) path_length[current_point.x()][current_point.y()] = min_cost min_cost = self.width * self.height for i in range(len(open_list)): current_point = open_list[i] temp_cost = path_length[current_point.x()][current_point.y()] + \ self.manhattan_length(current_point, self.radish) if temp_cost < min_cost: min_cost = temp_cost sequence = i temp_point = copy.deepcopy(open_list[sequence]) close_list.append(temp_point) if temp_point == self.radish: while True: self.path.append(copy.deepcopy(temp_point)) temp_point = parent_point[temp_point.x()][temp_point.y()] if temp_point.x() == -1: return [True, time.clock() - start_time] def save_map(self, file_path): """ save the map as a numpy matrix """ map_matrix = [[BASE_ROAD for i in range(self.width)] for j in range(self.height)] map_matrix = numpy.array(map_matrix).T for i in range(len(self.wall)): map_matrix[self.wall[i].x()][self.wall[i].y()] = WALL map_matrix[self.rabbit.x()][self.rabbit.y()] = RABBIT map_matrix[self.radish.x()][self.radish.y()] = RADISH map_matrix = numpy.array(map_matrix).T numpy.savetxt(file_path, map_matrix, fmt='%d') def load_map(self, file_path): """ read the map from a numpy matrix """ # 加转置保证地图文件和ui画面上物品位置匹配 map_matrix = numpy.loadtxt(file_path, dtype=int) self.path.clear() self.wall.clear() self.set_map_size(map_matrix.shape[1], map_matrix.shape[0]) # 存在才画出来 if len(numpy.argwhere(map_matrix == RABBIT)): self.set_rabbit(QPoint(numpy.argwhere(map_matrix == RABBIT)[0][1], numpy.argwhere(map_matrix == RABBIT)[0][0])) if len(numpy.argwhere(map_matrix == RADISH)): self.set_radish(QPoint(numpy.argwhere(map_matrix == RADISH)[0][1], numpy.argwhere(map_matrix == RADISH)[0][0])) temp_wall = numpy.argwhere(map_matrix == WALL) for i in range(temp_wall.shape[0]): self.set_wall(QPoint(temp_wall[i][1], temp_wall[i][0]))
class RenderArea(QWidget): Line, Points, Polyline, Polygon, Rect, RoundedRect, Ellipse, Arc, Chord, \ Pie, Path, Text, Pixmap = range(13) def __init__(self, machine, parent=None): super(RenderArea, self).__init__(parent) self.pen = QPen() self.brush = QBrush() self.antialiased = True self.setBackgroundRole(QPalette.Base) self.setAutoFillBackground(True) self.machine = machine self.dist_radius = min(self.width() / 4, self.height() / 4) * 1.5 self.dist_center = QPoint(self.width() / 2.0, self.height() / 2.0) self.n_states = len(self.machine.getStates()) self.state_radius = self.funcc(self.dist_radius, self.n_states) self.active = -1 self.t_active = -1 self.pts = [] #Brushes linearGradient = QLinearGradient(-self.state_radius, -self.state_radius, self.state_radius, self.state_radius) linearGradient.setColorAt(0.0, Qt.darkGreen) linearGradient.setColorAt(0.7, Qt.green) linearGradient.setColorAt(0.3, Qt.green) linearGradient.setColorAt(1.0, Qt.white) self.greenGradientBrush = QBrush(linearGradient) linearGradient = QLinearGradient(-self.state_radius, -self.state_radius, self.state_radius, self.state_radius) linearGradient.setColorAt(0.0, Qt.darkGray) linearGradient.setColorAt(0.7, Qt.lightGray) linearGradient.setColorAt(0.3, Qt.gray) linearGradient.setColorAt(1.0, Qt.white) self.grayGradientBrush = QBrush(linearGradient) self.setBrush(self.grayGradientBrush) #end brushes def funcc(self, r, n): return int((r*0.05) / (n*0.04)) def minimumSizeHint(self): return QSize(100, 100) def sizeHint(self): return QSize(400, 200) def setPen(self, pen): self.pen = pen self.update() def setBrush(self, brush): self.brush = brush self.update() def resizeEvent(self, event): self.dist_center = QPoint(self.width() / 2.0, self.height() / 2.0) self.dist_radius = min(self.width() / 4, self.height() / 4) * 1.5 self.state_radius = self.funcc(self.dist_radius, self.n_states) self.update() def poly(self, pts): return QPolygonF(map(lambda p: QPointF(*p), pts)) def wave(self): t = self.machine.getActiveTransition() if t != None: init = QPoint(t.getOrig()[0], t.getOrig()[1]) end = QPoint(t.getDest()[0], t.getDest()[1]) angle = t.getAngle() #print('processing transition', t.id, t.orig, t.dest) while t.isActive(): #for i in range(3): #for testing self.pts = [[init.x(), init.y()], [end.x(), end.y()]] if self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: while self.pts[0][0] <= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] >= self.pts[1][1]: self.sumPoint(angle) elif self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: while self.pts[0][0] >= self.pts[1][0] and self.pts[0][1] <= self.pts[1][1]: self.sumPoint(angle) def sumPoint(self, angle): self.pts[0][0] += (self.state_radius * math.cos(angle) * 0.1) self.pts[0][1] -= (self.state_radius * math.sin(angle) * 0.1) self.update() QApplication.processEvents() time.sleep(0.025) def paintEvent(self, event): painter = QPainter(self) painter.setPen(self.pen) painter.setBrush(self.brush) if self.antialiased: painter.setRenderHint(QPainter.Antialiasing) angle_step = 360 / self.n_states painter.save() #Save_1. Save the state of the system (push matrix) painter.translate(self.dist_center.x(), self.dist_center.y()) # go to the center of the render area painter.rotate(-180) #to start painting from the left side of the circle (clockwise) #center of the circumference where through we are going to paint our states x = self.dist_radius * math.cos(0) y = self.dist_radius * math.sin(0) for h in range(self.n_states): rot = angle_step * h # each state is equidistant from the others. We paint them in circles painter.save() #Save_2 painter.rotate(rot) #now our system is pointing to the next state to be drawn painter.translate(x,y) #now our origin is in the center of the next state to be drawn #if the state is active, fill it green if self.machine.getState(h).isActive(): painter.setBrush(self.greenGradientBrush) painter.drawEllipse(QPoint(0,0), self.state_radius, self.state_radius) #draw the new state #global position of transformed coordinates (before any transformation, origin at top-left corner) gx = painter.worldTransform().map(QPoint(0,0)).x() gy = painter.worldTransform().map(QPoint(0,0)).y() self.machine.getState(h).setPos(gx, gy) #store the center of the state without any transformation applied # text transformation. Our origin is still in the center of the current state painter.save() #Save_3 painter.rotate(180) #making the text go vertical painter.rotate(-rot) #undoing the rotation made for painting the state. No the text is horizontal font = painter.font(); font.setPixelSize(self.state_radius*.4); painter.setFont(font); rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2) painter.drawText(rect, Qt.AlignCenter, self.machine.getState(h).getName()); painter.restore() #Restore_3 #end text transformation painter.restore() #Restore_2 painter.restore() #Restore_1. Restore the state of the system (pop matrix) #drawing transitions. Line between states painter.save() # Save_4 pptv = QTransform() #Define a new transformation. Needed to rotate the system along other axis than Z pptv.translate(0, self.height()) #We are now at the bottom-left corner of the screen pptv.rotate(-180, Qt.XAxis) #Rotate along the X-axis so now we are in a typical cartesian system. painter.setTransform(pptv) #Apply the transformation states = self.machine.getStates() for state in states: transitions = state.getTransitions() for transition in transitions: #get the center of the origin and destination states in our current system state orig = QPoint(state.getPos()[0], state.getPos()[1]) end = QPoint(self.machine.getState(transition.getStateEnd()).getPos()[0], self.machine.getState(transition.getStateEnd()).getPos()[1]) # get those coordinates without transformation orig2 = QPoint(painter.worldTransform().map(orig)) end2 = QPoint(painter.worldTransform().map(end)) #get the angle between states centers and the horizon angle = math.atan2(end2.y() - orig2.y(), end2.x() - orig2.x()) #get the coordinates of the starting point of the transition (it starts in the bound of the state, not in the center) newX = self.state_radius * math.cos(angle) + orig2.x() newY = self.state_radius * math.sin(angle) + orig2.y() #now the transition starts at the border, not in the center orig2.setX(newX) orig2.setY(newY) #same for the destination state angle2 = math.atan2(orig2.y() - end2.y(), orig2.x() - end2.x()) newX2 = self.state_radius * math.cos(angle2) + end2.x() newY2 = self.state_radius * math.sin(angle2) + end2.y() end2.setX(newX2) end2.setY(newY2) #draw the line between the origin and destination states painter.drawLine(orig2, end2) #get the start and the end of the transition untransformed init = QPoint(painter.worldTransform().map(orig2)) end = QPoint(painter.worldTransform().map(end2)) #store that info transition.setOrig(init.x(), init.y()) transition.setDest(end.x(), end.y()) transition.setAngle(angle) painter.restore() #Restore_4 #Appliying style to the transitions painter.setPen(QPen(QColor(Qt.gray), 3)) for state in self.machine.getStates(): for transition in state.getTransitions(): #get the start and end coordinates of the transition i = QPoint(transition.getOrig()[0], transition.getOrig()[1]) o = QPoint(transition.getDest()[0], transition.getDest()[1]) painter.drawPolyline(i, o) #Drawing the arrow at the end of the transition painter.save() #Save_5 painter.setPen(QPen(QColor(Qt.gray), 2)) painter.translate(transition.getDest()[0],transition.getDest()[1]) #Go to the end of the transition painter.rotate(90 - transition.getAngle()*180/math.pi) #Rotate to point in the direction of the transition #coordinates of the arrow (triangle) a = QPoint(0,0) b = QPoint(-5,10) c = QPoint(5,10) #coordinates of the arrow untransformed a1 = painter.worldTransform().map(a) b1 = painter.worldTransform().map(b) c1 = painter.worldTransform().map(c) #Drawin the actual arrow pointer = QPolygon([a,b,c]) painter.drawPolygon(pointer) painter.restore() #Restore_5 #For the animation of the transition painter.save() #Save_6 if transition.isActive(): #if the current transition is the active one the wave function will be running, so it's updating the canvas painter.setPen(QPen(QColor(Qt.green), 3)) painter.drawPolyline(i,o) painter.setPen(QPen(QColor(Qt.gray), 3)) painter.drawPolyline(self.poly(self.pts)) #Draw the arrow in the active state (red arrow) painter.setBrush(QBrush(QColor(255, 0, 0))) painter.setPen(QPen(QColor(Qt.red), 2)) pointer = QPolygon([a1,b1,c1]) painter.drawPolygon(pointer) #Ball that follows the line animation for x, y in self.pts: painter.drawEllipse(QRectF(self.pts[0][0] - 4, self.pts[0][1] - 4, 8, 8)) painter.restore() #Restore_6 #Painting the text of the transition painter.save() #Save_7 pptv = QTransform() painter.setPen(QPen(QColor(Qt.black), 3)) #get the middle point of the transition middleX = (transition.getOrig()[0] + transition.getDest()[0]) /2 middleY = (transition.getOrig()[1] + transition.getDest()[1]) /2 pptv.translate(middleX, middleY) #translate to that point painter.setTransform(pptv) #apply the transformation font = painter.font(); font.setPixelSize(self.state_radius*.2); painter.setFont(font); rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2) name = str(transition.getId())+ '. ' + transition.getName() painter.drawText(rect, Qt.AlignCenter, name) painter.restore() #Restore_7 #paint the actual canvas painter.setPen(self.palette().dark().color()) painter.setBrush(Qt.NoBrush) painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1)) def start(self,n): '''print('active', n) self.active = n%3 self.deactivateAll() self.machine.setStateActive(self.active, True) #time.sleep(5) self.t_active = n%3 self.wave() for i in range(self.n_states): print('active', i) self.active = i self.deactivateAll() self.machine.setStateActive(self.active, True) self.update() QApplication.processEvents() time.sleep(2) self.t_active = i self.deactivateAll() self.machine.setTransitionActive (self.t_active, True) for i in self.machine.getTransitions(): print (i.isActive()) self.update() QApplication.processEvents() self.wave()''' def stop(self): self.machine.deactivateAll()
def a_star_searching(self): """ Use A* algorithm to find the best path between rabbit and radish :return: """ # time.clock() to compute the running time of a_star_searching if self.rabbit == QPoint(-1,-1) or self.radish == QPoint(-1,-1): return [False] start_time = time.clock() self.path.clear() open_list, close_list = [], [] # temp_point 在生成open表时有用,current_point表示目前搜索到的点 temp_point, current_point = QPoint(), QPoint() path_length = [[0 for i in range(self.height)] for j in range(self.width)] parent_point = [[QPoint(-1, -1) for i in range(self.height)] for j in range(self.width)] min_cost, temp_cost, sequence= 0, 0, 0 close_list.append(self.rabbit) while True: open_list.clear() # find the adjacent points of every point in close_list for i in range(len(close_list)): current_point = close_list[i] # temp_point is the adjacent points(4) of current_point temp_point = [copy.deepcopy(current_point) for i in range(4)] temp_point[0].setX(temp_point[0].x()-1) temp_point[1].setX(temp_point[1].x()+1) temp_point[2].setY(temp_point[2].y()-1) temp_point[3].setY(temp_point[3].y()+1) for j in range(4): if close_list.count(temp_point[j]) == 0 : if open_list.count(temp_point[j]) == 0: if self.is_valid(temp_point[j]): # use deepcopy to assure the open_list unchangeable when # the temp_point changes open_list.append(copy.deepcopy(temp_point[j])) if len(open_list) == 0: return [False] # find all the distance of between points in open_list and beginning point for i in range(len(open_list)): current_point = open_list[i] # makes the min_cost as large as possible min_cost = self.width * self.height for j in range(len(close_list)): temp_point = close_list[j] if self.manhattan_length(current_point, temp_point) == 1: temp_cost = path_length[temp_point.x()][temp_point.y()] + 1 if temp_cost < min_cost: min_cost = copy.deepcopy(temp_cost) sequence = j parent_point[current_point.x()][current_point.y()] = copy.deepcopy(close_list[sequence]) path_length[current_point.x()][current_point.y()] = min_cost min_cost = self.width * self.height for i in range(len(open_list)): current_point = open_list[i] temp_cost = path_length[current_point.x()][current_point.y()] + \ self.manhattan_length(current_point, self.radish) if temp_cost < min_cost: min_cost = temp_cost sequence = i temp_point = copy.deepcopy(open_list[sequence]) close_list.append(temp_point) if temp_point == self.radish: while True: self.path.append(copy.deepcopy(temp_point)) temp_point = parent_point[temp_point.x()][temp_point.y()] if temp_point.x() == -1: return [True, time.clock() - start_time]
def mouseMoveEvent(self, event): delta = QPoint(event.globalPos() - self.oldPos) print(delta.x(), delta.y()) self.MainWindow.move(self.MainWindow.x() + delta.x(), self.MainWindow.y() + delta.y()) self.oldPos = event.globalPos()
def mouseMoveEvent(self, e): delta = QPoint(e.globalPos() - self.oldPos) self.move(self.x() + delta.x(), self.y() + delta.y()) self.oldPos = e.globalPos()
class PictureBox(QLabel): changedNumberRegions = pyqtSignal(int) def __init__(self, image, regions, parent=None): QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() self.regions = None self.image = image def region_to_rect(region): y1, x1, y2, x2 = region.bbox return QRect(x1, y1, x2 - x1, y2 - y1) self.regions = list(map(region_to_rect, regions)) self._update_picture() def mousePressEvent(self, event): pal = QPalette() if event.button() == Qt.LeftButton: pal.setBrush(QPalette.Highlight, QBrush(Qt.blue)) elif event.button() == Qt.RightButton: pal.setBrush(QPalette.Highlight, QBrush(Qt.green)) self.rubberBand.setPalette(pal) self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull(): self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: drawnRect = QRect(self.origin, event.pos()).normalized() for region in self.getIntersectedRegions(drawnRect): self.regions.remove(region) elif event.button() == Qt.RightButton: drawnRect = QRect(self.origin, event.pos()).normalized() meanArea = np.mean([r.width() * r.height() for r in self.regions]) meanHeight = np.mean([r.height() for r in self.regions]) meanWidth = np.mean([r.width() for r in self.regions]) if drawnRect.width() * drawnRect.height() * 2 < meanArea: rect = QRect(self.origin.x() - meanWidth / 2, self.origin.y() - meanHeight / 2, meanWidth, meanHeight) self.regions.append(rect) else: self.regions.append(drawnRect) self.rubberBand.hide() self._update_picture() def getIntersectedRegions(self, drawnRect): result = [] for region in self.regions: if region.intersects(drawnRect): result.append(region) return result def _update_regions(self): pixmap = self._get_pixmap() paint = QPainter(pixmap) paint.setPen(QColor("green")) for region in self.regions: paint.drawRect(region) # rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr, # fill=False, edgecolor='green', linewidth=2) del paint return pixmap def savePicture(self, fname): pixmap = self._update_regions() return pixmap.save(fname) def _update_picture(self): pixmap = self._update_regions() self.setAlignment(Qt.AlignLeft | Qt.AlignTop) self.setPixmap(pixmap) self.changedNumberRegions.emit(len(self.regions)) def _get_pixmap(self): # Convert image to QImage qimg = qimage2ndarray.array2qimage(self.image, True) return QPixmap(qimg)
class GLWidget(QOpenGLWidget): clicked = pyqtSignal() PROGRAM_VERTEX_ATTRIBUTE, PROGRAM_TEXCOORD_ATTRIBUTE = range(2) vsrc = """ attribute highp vec4 vertex; attribute mediump vec4 texCoord; varying mediump vec4 texc; uniform mediump mat4 matrix; void main(void) { gl_Position = matrix * vertex; texc = texCoord; } """ fsrc = """ uniform sampler2D texture; varying mediump vec4 texc; void main(void) { gl_FragColor = texture2D(texture, texc.st); } """ coords = (((+1, -1, -1), (-1, -1, -1), (-1, +1, -1), (+1, +1, -1)), ((+1, +1, -1), (-1, +1, -1), (-1, +1, +1), (+1, +1, +1)), ((+1, -1, +1), (+1, -1, -1), (+1, +1, -1), (+1, +1, +1)), ((-1, -1, -1), (-1, -1, +1), (-1, +1, +1), (-1, +1, -1)), ((+1, -1, +1), (-1, -1, +1), (-1, -1, -1), (+1, -1, -1)), ((-1, -1, +1), (+1, -1, +1), (+1, +1, +1), (-1, +1, +1))) def __init__(self, parent=None): super(GLWidget, self).__init__(parent) self.clearColor = QColor(Qt.black) self.xRot = 0 self.yRot = 0 self.zRot = 0 self.program = None self.lastPos = QPoint() def minimumSizeHint(self): return QSize(50, 50) def sizeHint(self): return QSize(200, 200) def rotateBy(self, xAngle, yAngle, zAngle): self.xRot += xAngle self.yRot += yAngle self.zRot += zAngle self.update() def setClearColor(self, color): self.clearColor = color self.update() def initializeGL(self): self.gl = self.context().versionFunctions() self.gl.initializeOpenGLFunctions() self.makeObject() self.gl.glEnable(self.gl.GL_DEPTH_TEST) self.gl.glEnable(self.gl.GL_CULL_FACE) vshader = QOpenGLShader(QOpenGLShader.Vertex, self) vshader.compileSourceCode(self.vsrc) fshader = QOpenGLShader(QOpenGLShader.Fragment, self) fshader.compileSourceCode(self.fsrc) self.program = QOpenGLShaderProgram() self.program.addShader(vshader) self.program.addShader(fshader) self.program.bindAttributeLocation('vertex', self.PROGRAM_VERTEX_ATTRIBUTE) self.program.bindAttributeLocation('texCoord', self.PROGRAM_TEXCOORD_ATTRIBUTE) self.program.link() self.program.bind() self.program.setUniformValue('texture', 0) self.program.enableAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE) self.program.enableAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE) self.program.setAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE, self.vertices) self.program.setAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE, self.texCoords) def paintGL(self): self.gl.glClearColor(self.clearColor.redF(), self.clearColor.greenF(), self.clearColor.blueF(), self.clearColor.alphaF()) self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT) m = QMatrix4x4() m.ortho(-0.5, 0.5, 0.5, -0.5, 4.0, 15.0) m.translate(0.0, 0.0, -10.0) m.rotate(self.xRot / 16.0, 1.0, 0.0, 0.0) m.rotate(self.yRot / 16.0, 0.0, 1.0, 0.0) m.rotate(self.zRot / 16.0, 0.0, 0.0, 1.0) self.program.setUniformValue('matrix', m) for i, texture in enumerate(self.textures): texture.bind() self.gl.glDrawArrays(self.gl.GL_TRIANGLE_FAN, i * 4, 4) def resizeGL(self, width, height): side = min(width, height) self.gl.glViewport((width - side) // 2, (height - side) // 2, side, side) def mousePressEvent(self, event): self.lastPos = event.pos() def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.rotateBy(8 * dy, 8 * dx, 0) elif event.buttons() & Qt.RightButton: self.rotateBy(8 * dy, 0, 8 * dx) self.lastPos = event.pos() def mouseReleaseEvent(self, event): self.clicked.emit() def makeObject(self): self.textures = [] self.texCoords = [] self.vertices = [] root = QFileInfo(__file__).absolutePath() for i in range(6): self.textures.append( QOpenGLTexture( QImage(root + ('/images/side%d.png' % (i + 1))).mirrored())) for j in range(4): self.texCoords.append(((j == 0 or j == 3), (j == 0 or j == 1))) x, y, z = self.coords[i][j] self.vertices.append((0.2 * x, 0.2 * y, 0.2 * z))
class OpenGLWidget(QOpenGLWidget): def __init__(self, parent, radius, quality): QOpenGLWidget.__init__(self, parent) self.__radius = radius self.__quality = quality self.__xRotation = 0 self.__yRotation = 0 self.__zRotation = 0 self.__lastPoint = QPoint() def sizeHint(self): return SIZE def minimumSizeHint(self): return MINIMUM_SIZE def initializeGL(self): glClearColor(0.0, 0.0, 0.0, 0.0) glEnable(GL_DEPTH_TEST) glShadeModel(GL_FLAT) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glLightfv(GL_LIGHT0, GL_POSITION, FIRST_LIGHT_POSITION) glEnable(GL_LIGHT1) glLightfv(GL_LIGHT1, GL_POSITION, SECOND_LIGHT_POSITION) def paintGL(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() glTranslatef(0.0, 0.0, -5.0) glRotatef(self.__xRotation / ROTATION_SPEED, 1.0, 0.0, 0.0) glRotatef(self.__yRotation / ROTATION_SPEED, 0.0, 1.0, 0.0) glRotatef(self.__zRotation / ROTATION_SPEED, 0.0, 0.0, 1.0) self.draw() def resizeGL(self, width, height): glMatrixMode(GL_PROJECTION) glLoadIdentity() aspect = width / height if aspect > 1: glOrtho(-DISTANCE * aspect, DISTANCE * aspect, -DISTANCE, DISTANCE, 1, 16) else: glOrtho(-DISTANCE, DISTANCE, -DISTANCE / aspect, DISTANCE / aspect, 1, 16) glMatrixMode(GL_MODELVIEW) def mousePressEvent(self, _event): self.__lastPoint = _event.pos() def mouseMoveEvent(self, _event): dx = _event.x() - self.__lastPoint.x() dy = _event.y() - self.__lastPoint.y() if _event.buttons() & Qt.LeftButton or _event.buttons & Qt.RightButton: self.set_xRotation(self.__xRotation + dy) self.set_yRotation(self.__yRotation + dx) def set_quality(self, quality): self.__quality = quality self.update() def set_radius(self, radius): self.__radius = radius self.update() def normalize_angle(self, angle): while angle < 0: angle += 360 while angle > 360: angle -= 360 def set_xRotation(self, angle): self.normalize_angle(angle) if angle != self.__xRotation: self.__xRotation = angle self.update() def set_yRotation(self, angle): self.normalize_angle(angle) if angle != self.__yRotation: self.__yRotation = angle self.update() def set_zRotation(self, angle): self.normalize_angle(angle) if angle != self.__zRotation: self.__zRotation = angle self.update() def draw(self): radius = self.__radius quality = self.__quality y_multiplier = pi / quality x_multiplier = 2.0 * y_multiplier glPolygonMode(GL_FRONT, GL_FILL) glBegin(GL_QUAD_STRIP) for y_index in range(quality): # theta is the latitude, ranging from 0 to pi theta = y_index * y_multiplier tex_Y = y_index / quality for x_index in range(quality): # phi is the longitude, ranging from 0 to 2*pi phi = x_index * x_multiplier tex_X = x_index / quality x = radius * sin(theta) * cos(phi) y = radius * sin(theta) * sin(phi) z = radius * cos(theta) glNormal3f(x, y, z) glTexCoord2f(tex_X, tex_Y) glVertex3f(x, y, z) theta_new = theta + y_multiplier x = radius * sin(theta_new) * cos(phi) y = radius * sin(theta_new) * sin(phi) z = radius * cos(theta_new) glNormal3f(x, y, z) glTexCoord2f(tex_X, tex_Y + 1 / self.__quality) glVertex3f(x, y, z) glEnd()
class Ui_MeasureWindow(QtWidgets.QWidget): def __init__(self, parent): super().__init__() self.main = parent sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) self.setSizePolicy(sizePolicy) self.setWindowTitle("Channel Measurement") self.setWindowIcon(QtGui.QIcon('res\\m_icon.ico')) #self.setWindowFlags(QtCore.Qt.WindowFlags(QtCore.Qt.FramelessWindowHint)) self.layout1 = QtWidgets.QHBoxLayout() self.tableWidget = QtWidgets.QTableWidget(self) self.tableWidget.setSizeAdjustPolicy( QtWidgets.QAbstractScrollArea.AdjustToContents) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setSizePolicy(sizePolicy) self.tableWidget.setColumnCount(12) self.tableWidget.setRowCount(0) self.tableWidget.setLineWidth(5) self.layout1.addWidget(self.tableWidget) self.layout1.setContentsMargins(0, 0, 0, 0) self.layout1.setSizeConstraint(QtWidgets.QLayout.SetMaximumSize) self.tableWidget.verticalHeader().setVisible(False) header_list = [ "Channel", "Vmin", "Vmax", "Vmean", "Vrms", "Vpk-pk", "Freq", "T Period", "PWidth+", "PWidth-", "Duty+", "Duty-" ] font = QtGui.QFont("Arial", 9) font.setBold(True) header_num = 0 for headers in header_list: header_item = QtWidgets.QTableWidgetItem(headers) header_item.setFont(font) self.tableWidget.setHorizontalHeaderItem(header_num, header_item) header_num += 1 self.tableWidget.resizeColumnsToContents() self.first_run = True #self.title_bar = custom_TitleBar(self) #self.layout.addWidget(self.title_bar) #flags=QtCore.Qt.WindowFlags(QtCore.Qt.FramelessWindowHint)# | QtCore.Qt.WindowStaysOnTopHint) #self.setWindowFlags(QtCore.Qt.WindowFlags(QtCore.Qt.FramelessWindowHint)) #self.title_bar.pressing = False self.freq_Pulse_Duty_list = [] self.Ch_Vmins = [] self.Ch_Vmaxs = [] self.Ch_Vmeans = [] self.Ch_Vrms = [] self.Ch_pk2pk = [] self.freq_Pulse_Duty_list_act = [] self.Ch_Vmins_act = [] self.Ch_Vmaxs_act = [] self.Ch_Vrms_act = [] self.Ch_pk2pk_act = [] self.closed = False self.shown = False self.was_shown = False self.resize_by_func = False self.round_factor_is_set = True self.round_factor = 3 self.opacity_ = 160 self.initial_members_count = 0 self.Each_Row_height_saved = 0 self.Actual_win_height_0_row_saved = 0 self.table_height_offset_saved = 0 self.tableWidget_mWin_size_same = False self.win_pos = QPoint(0, 0) self.get_config() def update_(self): self.calc_Vmean() self.calc_Vrms() self.calc_pk2pk() self.Calc_Times() measurement_list = [] measurement_list_actual = [] ch_name_list = [] mem = 0 for members in self.main.ch_name_col_list: ch_name_list.append(self.main.ch_name_col_list[mem][0]) mem += 1 Ch_Vmeans = self.set_Units(self.Ch_Vmeans, 0) measurement_list = [ ch_name_list, self.Ch_Vmins, self.Ch_Vmaxs, Ch_Vmeans, self.Ch_Vrms, self.Ch_pk2pk, self.freq_Pulse_Duty_list ] measurement_list_actual = [ ch_name_list, self.Ch_Vmins_act, self.Ch_Vmaxs_act, self.Ch_Vmeans, self.Ch_Vrms_act, self.Ch_pk2pk_act, self.freq_Pulse_Duty_list_act ] ##print(measurement_list) row_num = 0 ###CH_name Vmin, Vmax, Vmean Vrms PktoPk Freq TPeriod Pwidth+ PWidth- Duty+ Duty - for members in self.main.ch_name_col_list: self.tableWidget.insertRow(row_num) for i in range(self.tableWidget.columnCount()): if i <= 5: ##print("Items:",row_num,i,measurement_list[i][row_num]) self.tableWidget.setItem( row_num, i, QtWidgets.QTableWidgetItem( measurement_list[i][row_num])) if i != 0: self.tableWidget.item(row_num, i).setToolTip( str(measurement_list_actual[i][row_num]) + "mv") else: self.tableWidget.item(row_num, i).setToolTip( str(measurement_list_actual[i][row_num])) self.tableWidget.item(row_num, i).setTextAlignment(Qt.AlignCenter) col = QtGui.QColor(members[1]) col.setAlpha(self.opacity_) self.tableWidget.item(row_num, i).setBackground(QtGui.QColor(col)) else: j = i - 6 self.tableWidget.setItem( row_num, i, QtWidgets.QTableWidgetItem( measurement_list[6][row_num][j])) if j == 0: self.tableWidget.item(row_num, i).setToolTip( str(measurement_list_actual[6][row_num][j]) + "Hz") elif j > 0 and j < 4: self.tableWidget.item(row_num, i).setToolTip( str(measurement_list_actual[6][row_num][j]) + "s") else: self.tableWidget.item(row_num, i).setToolTip( str(measurement_list_actual[6][row_num][j]) + "%") col = QtGui.QColor(members[1]) col.setAlpha(self.opacity_) self.tableWidget.item(row_num, i).setBackground(QtGui.QColor(col)) self.tableWidget.item(row_num, i).setTextAlignment(Qt.AlignCenter) #print(row_num," ",i) row_num += 1 self.initial_members_count = row_num self.tableWidget.resizeColumnsToContents() self.tableWidget.resizeRowsToContents() self.first_run = False def Update_UI(self): if self.initial_members_count != len( self.main.ch_name_col_list) or self.main.file_edited == True: if self.shown == True: Each_Row_height, Actual_win_height_0_row, table_height_offset = self.read_dimentions( ) elif self.was_shown: Each_Row_height = self.Each_Row_height_saved Actual_win_height_0_row = self.Actual_win_height_0_row_saved table_height_offset = self.table_height_offset_saved for i in range(self.tableWidget.rowCount()): self.tableWidget.removeRow(0) self.first_run = True self.update_() if self.shown == True or self.was_shown == True: TH = int((self.tableWidget.rowCount() * Each_Row_height) + Actual_win_height_0_row) #print("TH=",TH) self.resize_by_func = True self.tableWidget.resize(self.tableWidget.size().width(), TH + table_height_offset) self.resize(self.size().width(), TH) #print("MeasureWin Size Updated") self.activateWindow() def read_dimentions(self): mWin_Height = self.size().height() table_height = self.tableWidget.height() table_height_offset = table_height - mWin_Height T_row_Height = 0 row_count = self.tableWidget.rowCount() for i in range(row_count): T_row_Height += self.tableWidget.rowHeight(i) Each_Row_height = T_row_Height / row_count Actual_win_height_0_row = mWin_Height - T_row_Height ##print("AWH=",Actual_win_height_0_row," Prow_count=",row_count,"PT_row_Height=",T_row_Height,"mWin_Height=",mWin_Height,"table_height=",table_height) return Each_Row_height, Actual_win_height_0_row, table_height_offset ############################################################ MATH ########################################################################### def calc_Vmean(self): ch_num = 0 for members in self.main.ch_name_col_list: self.Ch_Vmeans.append(np.mean(self.main.y[ch_num])) ch_num += 1 def calc_Vrms(self): ch_num = 0 Ch_Vrms = [] vrms = [] vsq = [] for members in self.main.ch_name_col_list: vsq = np.square(self.main.y[ch_num]) Ch_Vrms.append(np.sqrt(np.mean(vsq))) ch_num += 1 self.Ch_Vrms_act = Ch_Vrms self.Ch_Vrms = self.set_Units(Ch_Vrms, 0) def calc_pk2pk(self): ch_num = 0 Ch_pk2pk = [] Ch_Vmins = [] Ch_Vmaxs = [] for members in self.main.ch_name_col_list: vmax = max(self.main.y[ch_num]) vmin = min(self.main.y[ch_num]) Ch_pk2pk.append(vmax - vmin) ##print(vmax-vmin) Ch_Vmins.append(vmin) Ch_Vmaxs.append(vmax) ch_num += 1 self.Ch_pk2pk = self.set_Units(Ch_pk2pk, 0) self.Ch_pk2pk_act = Ch_pk2pk self.Ch_Vmaxs = self.set_Units(Ch_Vmaxs, 0) self.Ch_Vmaxs_act = Ch_Vmaxs self.Ch_Vmins = self.set_Units(Ch_Vmins, 0) self.Ch_Vmins_act = Ch_Vmins def Calc_Times(self): self.freq_Pulse_Duty_list_act = [] self.freq_Pulse_Duty_list = [] #self.calc_Vmean() y_mean = self.Ch_Vmeans ch_num = 0 self.freq_Pulse_Duty_list = [] for members in self.main.ch_name_col_list: #print("CH NAME:",self.main.ch_name_col_list[ch_num][0]," CH Vmean:",y_mean[ch_num]) FPD = self.single_Ch_freq( ch_num, y_mean[ch_num] ) #freq,period,mean_pos_pulse,mean_neg_pulse,Duty_P,Duty_N self.freq_Pulse_Duty_list_act.append(FPD) FPD = self.set_Units(FPD, 1) self.freq_Pulse_Duty_list.append(FPD) ch_num += 1 def single_Ch_freq(self, ch_number, ch_V_mean): t_list = [] dt_list = [] pulse_bool_list = [] count_dir_bool = 0 for i in range(len(self.main.y[ch_number]) - 1): if self.main.y[ch_number][i + 1] > self.main.y[ch_number][ i] and self.main.y[ch_number][i + 1] > ch_V_mean: if count_dir_bool == -1: t_list.append(self.main.x[ch_number][i + 1]) pulse_bool_list.append(1) #print("line:",str(i+1),"X:",str(self.main.x[ch_number][i+1]),"Y:",str(self.main.y[ch_number][i+1]),"1") count_dir_bool = 1 elif self.main.y[ch_number][i + 1] < self.main.y[ch_number][ i] and self.main.y[ch_number][i + 1] < ch_V_mean: if count_dir_bool == 1: t_list.append(self.main.x[ch_number][i + 1]) pulse_bool_list.append(-1) #print("line:",str(i+1),"X:",str(self.main.x[ch_number][i+1]),"Y:",str(self.main.y[ch_number][i+1]),"-1") count_dir_bool = -1 for j in range((len(t_list) - 1)): dt = t_list[j + 1] - t_list[j] ##print("",",",t_list[j],",",",",pulse_bool_list[j],file=self.main.file_) ##print(dt,file=self.main.file_) ##print("",",",t_list[j+1],",",",",pulse_bool_list[j+1],file=self.main.file_) puse_bool = pulse_bool_list[j + 1] - pulse_bool_list[j] ##print(dt,",",t_list[j+1],",",t_list[j],",",puse_bool,file=self.main.file_) dt_list.append([dt, puse_bool]) #print(dt_list) #dt_list=sorted(dt_list,key=itemgetter(0),reverse=True) max_end_indx_pos = -1 max_end_indx_neg = -1 mean_pos_pulse = 0 mean_neg_pulse = 0 pos_pulse = [] neg_pulse = [] if len(dt_list) > 1: for i in range(len(dt_list)): if dt_list[i][1] == -2: pos_pulse.append(dt_list[i][0]) if dt_list[i][1] == 2: neg_pulse.append(dt_list[i][0]) pos_pulse = sorted(pos_pulse, reverse=True) neg_pulse = sorted(neg_pulse, reverse=True) for i in range(len(pos_pulse) - 1): rel_dev = (pos_pulse[i] - pos_pulse[i + 1]) / pos_pulse[i] #print("indx=",i," dtf=",dt_list[i+1]," dti=",dt_list[i]," rel_dev=",rel_dev) if rel_dev > 0.50: #deviations above 50% of the max pulse width is neglected... (Considering stray) max_end_indx_pos = i + 1 break for i in range(len(neg_pulse) - 1): rel_dev = (neg_pulse[i] - neg_pulse[i + 1]) / neg_pulse[i] #print("indx=",i," dtf=",dt_list[i+1]," dti=",dt_list[i]," rel_dev=",rel_dev) if rel_dev > 0.50: #deviations above 50% of the max pulse width is neglected... (Considering stray) max_end_indx_neg = i + 1 break if max_end_indx_pos >= 0: pos_pulse = pos_pulse[:max_end_indx_pos] if max_end_indx_neg >= 0: neg_pulse = neg_pulse[:max_end_indx_neg] mean_pos_pulse = np.mean(pos_pulse) mean_neg_pulse = np.mean(neg_pulse) mean_pulse = np.mean([mean_pos_pulse, mean_neg_pulse]) elif len(dt_list) == 1: if dt_list[0][1] == 2: mean_neg_pulse = dt_list[0][0] mean_pulse = mean_neg_pulse if dt_list[0][1] == -2: mean_pos_pulse = dt_list[0][0] mean_pulse = mean_pos_pulse Duty_P = (mean_pos_pulse / (mean_pos_pulse + mean_neg_pulse)) * 100 Duty_N = (mean_neg_pulse / (mean_pos_pulse + mean_neg_pulse)) * 100 period = 2 * mean_pulse freq = (1 / (2 * mean_pulse)) #print("Freq=",freq," +PWidth=",mean_pos_pulse," -PWidth=",mean_neg_pulse," Duty_P=",Duty_P," Duty_N",Duty_N) return freq, period, mean_pos_pulse, mean_neg_pulse, Duty_P, Duty_N def set_Units(self, data_list, measurable_flag): string_list = [] round_b = self.round_factor_is_set round_f = self.round_factor if measurable_flag == 0: ###volt for i in range(len(data_list)): if data_list[i] >= 1000: if round_b: string_list.append( str(round(data_list[i] / 1000, round_f)) + " V") else: string_list.append(str(data_list[i] / 1000) + " V") else: if round_b: string_list.append( str(round(data_list[i], round_f)) + " mV") else: string_list.append(str(data_list[i]) + " mV") elif measurable_flag == 1: ###timmings for i in range(len(data_list)): if i == 0: if data_list[i] >= 1000: if round_b: string_list.append( str(round(data_list[i] / 1000, round_f)) + " KHz") else: string_list.append(str(data_list[i]) + " KHz") else: if round_b: string_list.append( str(round(data_list[i], round_f)) + " Hz") else: string_list.append(str(data_list[i]) + " Hz") if i > 0 and i <= 3: unit_ = "" time_s = data_list[i] * 1e9 unit_ = "ns" if time_s > 800: time_s = time_s / 1000 ##in micros unit_ = "us" if time_s > 800: time_s = time_s / 1000 ##in millis unit_ = "ms" if time_s > 800: time_s = time_s / 1000 ##in Sec unit_ = "s" if round_b: string_list.append(str(round(time_s, round_f)) + unit_) else: string_list.append(str(time_s) + unit_) elif i > 3: if round_b: string_list.append( str(round(data_list[i], round_f)) + "%") else: string_list.append(str(data_list[i]) + "%") return string_list #############################################################EVENTS############################################################# def closeEvent(self, event): self.closed = True self.shown = False self.was_shown = True QtWidgets.QWidget.closeEvent(self, event) def showEvent(self, event): QtWidgets.QWidget.showEvent(self, event) #print("shown") if isinstance(self.win_pos, str) == False: self.move(self.win_pos) if self.tableWidget_mWin_size_same == False: self.resize( self.tableWidget.size().width() - self.main.popup_width_offset, self.tableWidget.size().height() - self.main.popup_height_offset) else: self.resize(self.tableWidget.size().width(), self.tableWidget.size().height()) self.shown = True self.was_shown = False self.Each_Row_height_saved, self.Actual_win_height_0_row_saved, self.table_height_offset_saved = self.read_dimentions( ) self.closed = False def resizeEvent(self, event): QtWidgets.QWidget.resizeEvent(self, event) if self.shown == True and self.resize_by_func == False: #print("resize") self.tableWidget.resize(self.size().width(), self.size().height()) self.tableWidget_mWin_size_same = True self.resize_by_func = False def moveEvent(self, e): if self.closed == False: self.win_pos = self.pos() super(Ui_MeasureWindow, self).moveEvent(e) def get_pos(self): if isinstance(self.win_pos, str): return [0, 0] else: return self.win_pos.x(), self.win_pos.y() def set_pos(self, pos_): self.move(pos_[0], pos_[1]) def get_config(self): if self.main.conf.Measurement_Window_Opacity != [None, False]: self.setWindowOpacity(self.main.conf.Measurement_Window_Opacity) if self.main.conf.Measurement_Window_always_on_top != [None, False]: if self.main.conf.Measurement_Window_always_on_top: self.setWindowFlags( QtCore.Qt.WindowFlags(QtCore.Qt.WindowStaysOnTopHint)) else: self.setWindowFlags(QtCore.Qt.WindowFlags())
def fillRegion(layer, fillOrigin): # Create that region that will hold the fill fillRegion = QRegion() # Silently quit if parameters are unsatisfactory if (not layer.contains(fillOrigin)): return fillRegion # Cache cell that we will match other cells against matchCell = layer.cellAt(fillOrigin) # Grab map dimensions for later use. layerWidth = layer.width() layerHeight = layer.height() layerSize = layerWidth * layerHeight # Create a queue to hold cells that need filling fillPositions = QList() fillPositions.append(fillOrigin) # Create an array that will store which cells have been processed # This is faster than checking if a given cell is in the region/list processedCellsVec = QVector() for i in range(layerSize): processedCellsVec.append(0xff) processedCells = processedCellsVec # Loop through queued positions and fill them, while at the same time # checking adjacent positions to see if they should be added while (not fillPositions.empty()): currentPoint = fillPositions.takeFirst() startOfLine = currentPoint.y() * layerWidth # Seek as far left as we can left = currentPoint.x() while (left > 0 and layer.cellAt(left - 1, currentPoint.y()) == matchCell): left -= 1 # Seek as far right as we can right = currentPoint.x() while (right + 1 < layerWidth and layer.cellAt(right + 1, currentPoint.y()) == matchCell): right += 1 # Add cells between left and right to the region fillRegion += QRegion(left, currentPoint.y(), right - left + 1, 1) # Add cell strip to processed cells for i in range(startOfLine + left, right + startOfLine, 1): processedCells[i] = 1 # These variables cache whether the last cell was added to the queue # or not as an optimization, since adjacent cells on the x axis # do not need to be added to the queue. lastAboveCell = False lastBelowCell = False # Loop between left and right and check if cells above or # below need to be added to the queue for x in range(left, right+1): fillPoint = QPoint(x, currentPoint.y()) # Check cell above if (fillPoint.y() > 0): aboveCell = QPoint(fillPoint.x(), fillPoint.y() - 1) if (not processedCells[aboveCell.y() * layerWidth + aboveCell.x()] and layer.cellAt(aboveCell) == matchCell): # Do not add the above cell to the queue if its # x-adjacent cell was added. if (not lastAboveCell): fillPositions.append(aboveCell) lastAboveCell = True else: lastAboveCell = False processedCells[aboveCell.y() * layerWidth + aboveCell.x()] = 1 # Check cell below if (fillPoint.y() + 1 < layerHeight): belowCell = QPoint(fillPoint.x(), fillPoint.y() + 1) if (not processedCells[belowCell.y() * layerWidth + belowCell.x()] and layer.cellAt(belowCell) == matchCell): # Do not add the below cell to the queue if its # x-adjacent cell was added. if (not lastBelowCell): fillPositions.append(belowCell) lastBelowCell = True else: lastBelowCell = False processedCells[belowCell.y() * layerWidth + belowCell.x()] = 1 return fillRegion
class GLWidget(QOpenGLWidget): xRotationChanged = pyqtSignal(int) yRotationChanged = pyqtSignal(int) zRotationChanged = pyqtSignal(int) def __init__(self, parent=None): super(GLWidget, self).__init__(parent) self.object = 0 self.xRot = 0 self.yRot = 0 self.zRot = 0 self.lastPos = QPoint() self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0) self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0) def minimumSizeHint(self): return QSize(50, 50) def sizeHint(self): return QSize(400, 400) def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle self.xRotationChanged.emit(angle) self.update() def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle self.yRotationChanged.emit(angle) self.update() def setZRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.zRot: self.zRot = angle self.zRotationChanged.emit(angle) self.update() def initializeGL(self): self.gl = self.context().versionFunctions() self.gl.initializeOpenGLFunctions() self.setClearColor(self.trolltechPurple.darker()) self.object = self.makeObject() self.gl.glShadeModel(self.gl.GL_FLAT) self.gl.glEnable(self.gl.GL_DEPTH_TEST) self.gl.glEnable(self.gl.GL_CULL_FACE) def paintGL(self): self.gl.glClear( self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT) self.gl.glLoadIdentity() self.gl.glTranslated(0.0, 0.0, -10.0) self.gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0) self.gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0) self.gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0) self.gl.glCallList(self.object) def resizeGL(self, width, height): side = min(width, height) if side < 0: return self.gl.glViewport((width - side) // 2, (height - side) // 2, side, side) self.gl.glMatrixMode(self.gl.GL_PROJECTION) self.gl.glLoadIdentity() self.gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0) self.gl.glMatrixMode(self.gl.GL_MODELVIEW) def mousePressEvent(self, event): self.lastPos = event.pos() def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.setXRotation(self.xRot + 8 * dy) self.setYRotation(self.yRot + 8 * dx) elif event.buttons() & Qt.RightButton: self.setXRotation(self.xRot + 8 * dy) self.setZRotation(self.zRot + 8 * dx) self.lastPos = event.pos() def makeObject(self): genList = self.gl.glGenLists(1) self.gl.glNewList(genList, self.gl.GL_COMPILE) self.gl.glBegin(self.gl.GL_QUADS) x1 = +0.06 y1 = -0.14 x2 = +0.14 y2 = -0.06 x3 = +0.08 y3 = +0.00 x4 = +0.30 y4 = +0.22 self.quad(x1, y1, x2, y2, y2, x2, y1, x1) self.quad(x3, y3, x4, y4, y4, x4, y3, x3) self.extrude(x1, y1, x2, y2) self.extrude(x2, y2, y2, x2) self.extrude(y2, x2, y1, x1) self.extrude(y1, x1, x1, y1) self.extrude(x3, y3, x4, y4) self.extrude(x4, y4, y4, x4) self.extrude(y4, x4, y3, x3) NumSectors = 200 for i in range(NumSectors): angle1 = (i * 2 * math.pi) / NumSectors x5 = 0.30 * math.sin(angle1) y5 = 0.30 * math.cos(angle1) x6 = 0.20 * math.sin(angle1) y6 = 0.20 * math.cos(angle1) angle2 = ((i + 1) * 2 * math.pi) / NumSectors x7 = 0.20 * math.sin(angle2) y7 = 0.20 * math.cos(angle2) x8 = 0.30 * math.sin(angle2) y8 = 0.30 * math.cos(angle2) self.quad(x5, y5, x6, y6, x7, y7, x8, y8) self.extrude(x6, y6, x7, y7) self.extrude(x8, y8, x5, y5) self.gl.glEnd() self.gl.glEndList() return genList def quad(self, x1, y1, x2, y2, x3, y3, x4, y4): self.setColor(self.trolltechGreen) self.gl.glVertex3d(x1, y1, -0.05) self.gl.glVertex3d(x2, y2, -0.05) self.gl.glVertex3d(x3, y3, -0.05) self.gl.glVertex3d(x4, y4, -0.05) self.gl.glVertex3d(x4, y4, +0.05) self.gl.glVertex3d(x3, y3, +0.05) self.gl.glVertex3d(x2, y2, +0.05) self.gl.glVertex3d(x1, y1, +0.05) def extrude(self, x1, y1, x2, y2): self.setColor(self.trolltechGreen.darker(250 + int(100 * x1))) self.gl.glVertex3d(x1, y1, +0.05) self.gl.glVertex3d(x2, y2, +0.05) self.gl.glVertex3d(x2, y2, -0.05) self.gl.glVertex3d(x1, y1, -0.05) def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle def setClearColor(self, c): self.gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()) def setColor(self, c): self.gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
def mouseMoveEvent(self, event: QMouseEvent): if self.scene() is None: return cursor = self.cursor().shape() if self.grab_start is not None: move = self.grab_start.x() - event.pos().x() self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + move) self.grab_start = event.pos() return if self.separation_area_moving: y_sep = self.mapToScene(event.pos()).y() y = self.sceneRect().y() h = self.sceneRect().height() if y < y_sep < y + h: self.scene().draw_sep_area(y_sep) self.sep_area_moving.emit(y_sep) elif self.is_pos_in_separea(self.mapToScene(event.pos())): self.setCursor(Qt.SplitVCursor) elif cursor == Qt.SplitVCursor: self.unsetCursor() if self.selection_area.finished and not self.selection_area.resizing: pos = self.mapToScene(event.pos()) roi_edge = self.selection_area.get_selected_edge( pos, self.view_rect().width()) if roi_edge is None and cursor == Qt.SplitHCursor: self.unsetCursor() return elif roi_edge == 0 or roi_edge == 1: self.setCursor(Qt.SplitHCursor) if event.buttons() == Qt.LeftButton and self.selection_area.resizing: if self.selection_area.selected_edge == 0: start = self.mapToScene(event.pos()) self.set_selection_area(x=start.x()) self.scroll_mouse(start.x()) return if self.selection_area.selected_edge == 1: start = QPoint(self.selection_area.rect().x(), self.selection_area.rect().y()) end = self.mapToScene(event.pos()) self.set_selection_area(w=end.x() - start.x()) self.scroll_mouse(end.x()) return if self.mouse_press_pos is None: return self.mouse_pos = event.pos() if event.buttons( ) == Qt.LeftButton and not self.selection_area.finished: start = self.mapToScene(self.mouse_press_pos) end = self.mapToScene(self.mouse_pos) self.set_selection_area(w=end.x() - start.x()) self.scroll_mouse(end.x())
class TileSelectionTool(AbstractTileTool): def __init__(self, parent = None): super().__init__(self.tr("Rectangular Select"), QIcon(":images/22x22/stock-tool-rect-select.png"), QKeySequence(self.tr("R")), parent) self.mSelectionMode = SelectionMode.Replace self.mSelecting = False self.setTilePositionMethod(TilePositionMethod.BetweenTiles) self.mSelectionStart = QPoint() def tr(self, sourceText, disambiguation = '', n = -1): return QCoreApplication.translate('TileSelectionTool', sourceText, disambiguation, n) def mousePressed(self, event): button = event.button() modifiers = event.modifiers() if (button == Qt.LeftButton): if (modifiers == Qt.ControlModifier): self.mSelectionMode = SelectionMode.Subtract elif (modifiers == Qt.ShiftModifier): self.mSelectionMode = SelectionMode.Add elif (modifiers == (Qt.ControlModifier | Qt.ShiftModifier)): self.mSelectionMode = SelectionMode.Intersect else: self.mSelectionMode = SelectionMode.Replace self.mSelecting = True self.mSelectionStart = self.tilePosition() self.brushItem().setTileRegion(QRegion()) def mouseReleased(self, event): if (event.button() == Qt.LeftButton): self.mSelecting = False document = self.mapDocument() selection = document.selectedArea() area = self.selectedArea() x = self.mSelectionMode if x==SelectionMode.Replace: selection = area elif x==SelectionMode.Add: selection += area elif x==SelectionMode.Subtract: selection = selection.xored(QRegion(area)) elif x==SelectionMode.Intersect: selection &= area if (selection != document.selectedArea()): cmd = ChangeSelectedArea(document, selection) document.undoStack().push(cmd) self.brushItem().setTileRegion(QRegion()) self.updateStatusInfo() def languageChanged(self): self.setName(self.tr("Rectangular Select")) self.setShortcut(QKeySequence(self.tr("R"))) def tilePositionChanged(self, tilePos): if (self.mSelecting): self.brushItem().setTileRegion(self.selectedArea()) def updateStatusInfo(self): if (not self.isBrushVisible() or not self.mSelecting): super().updateStatusInfo() return pos = self.tilePosition() area = self.selectedArea() self.setStatusInfo(self.tr("%d, %d - Rectangle: (%d x %d)"%((pos.x()), pos.y(), area.width(), area.height()))) def selectedArea(self): tilePos = self.tilePosition() pos = QPoint(min(tilePos.x(), self.mSelectionStart.x()), min(tilePos.y(), self.mSelectionStart.y())) size = QSize(abs(tilePos.x() - self.mSelectionStart.x()), abs(tilePos.y() - self.mSelectionStart.y())) return QRect(pos, size)
def move(self, pos): # make new pos to center pos = QPoint(pos.x() - self.width() * 0.5, pos.y() - self.height() * 0.5) # make this always on top self.raise_() QWidget.move(self, pos)
class Overlay(QWidget): def __init__(self, parent, binpath): super().__init__(parent) sizePolicy = QSizePolicy() sizePolicy.setHorizontalPolicy(QSizePolicy.Maximum) sizePolicy.setVerticalPolicy(QSizePolicy.Maximum) #self.setSizePolicy(sizePolicy) self.setMouseTracking(True) self.on_selection = False self.selected = False self.c = Communicate() self.start_position = QPoint(0,0) self.last_position = QPoint(0,0) image = ( b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00" b"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00" b"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00" b"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00" b"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00" b"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") im = QImage(image, 8,8, QImage.Format_RGB16) im = im.scaled(64,64) self.crop = QPixmap() self.crop.convertFromImage(im) def insideSelection(self, point): width = self.last_position.x() - self.start_position.x() height = self.last_position.y() - self.start_position.y() return ( point.x() > self.start_position.x() and point.x() < self.start_position.x() + width and point.y() > self.start_position.y() and point.y() < self.start_position.y() + height ) def mouseMoveEvent(self, event): if self.on_selection: self.last_position = event.pos() self.update() def mousePressEvent(self, QMouseEvent): if not self.insideSelection(QMouseEvent.pos()): self.on_selection = True self.selected = True self.start_position = QMouseEvent.pos() self.last_position = QMouseEvent.pos() self.update() def mouseDoubleClickEvent(self, QMouseEvent): if self.insideSelection(QMouseEvent.pos()): width = self.last_position.x() - self.start_position.x() height = self.last_position.y() - self.start_position.y() self.c.cropImage.emit(self.start_position.x(), self.start_position.y(), width,height) def mouseReleaseEvent(self, QMouseEvent): self.on_selection = False self.update() def enterEvent(self, event): return super().enterEvent(event) def leaveEvent(self, event): return super().enterEvent(event) def paintEvent(self, e): qp = QPainter() qp.begin(self) #self.drawWidget(qp) if self.selected: qp.setCompositionMode(QPainter.CompositionMode_HardLight) qp.setBrush(QColor(0, 0, 0, 128)) qp.drawRect(0,0, self.width(), self.height()) qp.setCompositionMode(QPainter.CompositionMode_Overlay) qp.setBrush(QColor(255, 255, 255, 255)) width = self.last_position.x() - self.start_position.x() height = self.last_position.y()-self.start_position.y() qp.drawRect(self.start_position.x(), self.start_position.y(), width, height) qp.setCompositionMode(QPainter.CompositionMode_SourceOver) image_w = min([abs(width), abs(height), self.crop.width()]) #self.crop.width() image_h = image_w #self.crop.height() qp.drawPixmap(self.start_position.x() + width/2 - image_w/2, self.start_position.y() + height/2 - image_h/2, image_w, image_h, self.crop) qp.end()
class ScribbleArea(QWidget): def __init__(self, width, height, scaling_factor, foreground_color, background_color, enable_grid, grid_color, parent): super().__init__(parent) self.parent = parent self.scribbling = 0 self.width = width self.height = height self.scaling_factor = scaling_factor self.pen_width = 1 self.foreground_color = foreground_color self.background_color = background_color self.grid_enabled = enable_grid if grid_color is not None: self.grid_color = grid_color else: self.grid_color = self.palette().color(QPalette.Window) self.image = QImage(QSize(width, height), QImage.Format_RGB32) self.setFixedSize(width*self.scaling_factor, height*self.scaling_factor) self.last_point = QPoint() self.clear_image() def set_foreground_color(self, color): self.foreground_color = color def array_draw(self, r, g, b, scale=1): for i in range(len(r)): self.image.setPixel(QPoint(i%self.width, i//self.width), (r[i]*scale << 16) | (g[i]*scale << 8) | b[i]*scale) self.update() def fill_image(self, color): self.image.fill(color) self.update() def clear_image(self): self.image.fill(self.background_color) self.update() def mousePressEvent(self, event): self.parent.scribbling_started.emit() if event.button() == Qt.LeftButton: self.last_point = event.pos() self.scribbling = 1 elif event.button() == Qt.RightButton: self.last_point = event.pos() self.scribbling = 2 def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) and self.scribbling == 1: self.draw_line_to(event.pos()) elif (event.buttons() & Qt.RightButton) and self.scribbling == 2: self.draw_line_to(event.pos()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.scribbling == 1: self.draw_line_to(event.pos()) self.scribbling = 0 elif event.button() == Qt.RightButton and self.scribbling == 2: self.draw_line_to(event.pos()) self.scribbling = 0 def paintEvent(self, event): painter = QPainter(self) painter.drawImage(QRect(0, 0, super().width(), super().height()), self.image) if self.grid_enabled: painter.setPen(QPen(self.grid_color)) for x in range(1, self.width): painter.drawLine(x * self.scaling_factor, 0, x * self.scaling_factor, super().height()) for y in range(1, self.height): painter.drawLine(0, y * self.scaling_factor, super().width(), y * self.scaling_factor) self.parent.paint_overlay(event, painter) def draw_line_to(self, end_point): painter = QPainter(self.image) painter.setPen(QPen(self.foreground_color if self.scribbling == 1 else self.background_color, self.pen_width, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(QPoint(self.last_point.x()//self.scaling_factor, self.last_point.y()//self.scaling_factor), QPoint(end_point.x()//self.scaling_factor, end_point.y()//self.scaling_factor)) self.update() self.last_point = QPoint(end_point)
class MandelbrotWidget(QWidget): def __init__(self, parent=None): super(MandelbrotWidget, self).__init__(parent) self.thread = RenderThread() self.pixmap = QPixmap() self.pixmapOffset = QPoint() self.lastDragPos = QPoint() self.centerX = DefaultCenterX self.centerY = DefaultCenterY self.pixmapScale = DefaultScale self.curScale = DefaultScale self.thread.renderedImage.connect(self.updatePixmap) self.setWindowTitle("Mandelbrot") self.setCursor(Qt.CrossCursor) self.resize(550, 400) def paintEvent(self, event): painter = QPainter(self) painter.fillRect(self.rect(), Qt.black) if self.pixmap.isNull(): painter.setPen(Qt.white) painter.drawText(self.rect(), Qt.AlignCenter, "Rendering initial image, please wait...") return if self.curScale == self.pixmapScale: painter.drawPixmap(self.pixmapOffset, self.pixmap) else: scaleFactor = self.pixmapScale / self.curScale newWidth = int(self.pixmap.width() * scaleFactor) newHeight = int(self.pixmap.height() * scaleFactor) newX = self.pixmapOffset.x() + (self.pixmap.width() - newWidth) / 2 newY = self.pixmapOffset.y() + (self.pixmap.height() - newHeight) / 2 painter.save() painter.translate(newX, newY) painter.scale(scaleFactor, scaleFactor) exposed, _ = painter.matrix().inverted() exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1) painter.drawPixmap(exposed, self.pixmap, exposed) painter.restore() text = "Use mouse wheel or the '+' and '-' keys to zoom. Press and " \ "hold left mouse button to scroll." metrics = painter.fontMetrics() textWidth = metrics.width(text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(0, 0, 0, 127)) painter.drawRect((self.width() - textWidth) / 2 - 5, 0, textWidth + 10, metrics.lineSpacing() + 5) painter.setPen(Qt.white) painter.drawText((self.width() - textWidth) / 2, metrics.leading() + metrics.ascent(), text) def resizeEvent(self, event): self.thread.render(self.centerX, self.centerY, self.curScale, self.size()) def keyPressEvent(self, event): if event.key() == Qt.Key_Plus: self.zoom(ZoomInFactor) elif event.key() == Qt.Key_Minus: self.zoom(ZoomOutFactor) elif event.key() == Qt.Key_Left: self.scroll(-ScrollStep, 0) elif event.key() == Qt.Key_Right: self.scroll(+ScrollStep, 0) elif event.key() == Qt.Key_Down: self.scroll(0, -ScrollStep) elif event.key() == Qt.Key_Up: self.scroll(0, +ScrollStep) else: super(MandelbrotWidget, self).keyPressEvent(event) def wheelEvent(self, event): numDegrees = event.angleDelta().y() / 8 numSteps = numDegrees / 15.0 self.zoom(pow(ZoomInFactor, numSteps)) def mousePressEvent(self, event): if event.buttons() == Qt.LeftButton: self.lastDragPos = QPoint(event.pos()) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.pixmapOffset += event.pos() - self.lastDragPos self.lastDragPos = QPoint(event.pos()) self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.pixmapOffset += event.pos() - self.lastDragPos self.lastDragPos = QPoint() deltaX = (self.width() - self.pixmap.width()) / 2 - self.pixmapOffset.x() deltaY = (self.height() - self.pixmap.height()) / 2 - self.pixmapOffset.y() self.scroll(deltaX, deltaY) def updatePixmap(self, image, scaleFactor): if not self.lastDragPos.isNull(): return self.pixmap = QPixmap.fromImage(image) self.pixmapOffset = QPoint() self.lastDragPosition = QPoint() self.pixmapScale = scaleFactor self.update() def zoom(self, zoomFactor): self.curScale *= zoomFactor self.update() self.thread.render(self.centerX, self.centerY, self.curScale, self.size()) def scroll(self, deltaX, deltaY): self.centerX += deltaX * self.curScale self.centerY += deltaY * self.curScale self.update() self.thread.render(self.centerX, self.centerY, self.curScale, self.size())
class Settings(object): l = logging.getLogger('Settings') def __init__(self, fileName = 'notepad.ini'): self.fileName = fileName self.notepads = [] self.mainWindowSize = QSize(1200, 700) self.mainWindowPos = QPoint(240, 200) self.browserPath = [] def load(self): self.l.debug('Loading local settings ...') config = configparser.ConfigParser() config.read(self.fileName) # load dropbox configuration self.dropboxToken = '' if config.has_section('dropbox'): self.dropboxToken = config['dropbox'].get('dropboxToken') # load browser state if config.has_section('browser'): browserSettings = config['browser'] path = browserSettings.get('path') self.browserPath = ast.literal_eval(path) # load main window position and size if config.has_section('mainWindow'): windowSettings = config['mainWindow'] # read position pos = windowSettings.get('pos', '{},{}'.format(self.mainWindowPos.x(), self.mainWindowPos.y())).split(',') self.mainWindowPos = QPoint(int(pos[0]), int(pos[1])) # read size size = windowSettings.get('size', '{},{}'.format(self.mainWindowSize.width(), self.mainWindowSize.height())).split(',') self.mainWindowSize = QSize(int(size[0]), int(size[1])) # load notepads self.notepads = [] for s in config.sections(): if s.startswith('notepad_'): npDef = None npType = config.get(s, 'type') if npType == 'local': npDef = {'name' : config.get(s, 'name'), 'type' : npType, 'path' : config.get(s, 'path') } elif npType == 'dropbox': npDef = {'name' : config.get(s, 'name'), 'type' : npType } if npDef is not None: self.notepads.append(npDef) def dump(self, channel): self.l.debug('Saving local settings ...') config = configparser.ConfigParser() config.add_section('dropbox') config.set('dropbox', 'dropboxToken', self.dropboxToken) config.add_section('browser') config.set('browser', 'path', str(self.browserPath)) config.add_section('mainWindow') config.set('mainWindow', 'pos', '{},{}'.format(self.mainWindowPos.x(), self.mainWindowPos.y())) config.set('mainWindow', 'size', '{},{}'.format(self.mainWindowSize.width(), self.mainWindowSize.height())) idx = 0 for s in self.notepads: sectName = "notepad_{}".format(idx) idx += 1 config.add_section(sectName) config.set(sectName, 'name', s['name']) config.set(sectName, 'type', s['type']) if s['type'] == 'local': config.set(sectName, 'path', s['path']) config.write(channel) def save(self): with open(self.fileName, 'w') as configfile: self.dump(configfile) def getNotepads(self): return self.notepads def addNotepad(self, npDef): self.notepads.append(npDef) def setMainWindowPos(self, pos): self.mainWindowPos = pos def setBrowserPath(self, path): self.browserPath = path def setMainWindowSize(self, size): self.mainWindowSize = size def getMainWindowPos(self): return self.mainWindowPos def getMainWindowSize(self): return self.mainWindowSize def getBrowserPath(self): return self.browserPath def getDropboxToken(self): return self.dropboxToken def setDropboxToken(self, token): self.dropboxToken = token
class WindMill(QLabel): set_ = pyqtSignal() def __init__(self, father, top): super().__init__('', father) self.set_.connect(set_wall) self.father, self.top = father, top self.setGeometry(0, 0, 75, 75) self.pix = QPixmap('image/windmill.png') self.setToolTip('来点好玩的') self.handle = False self.pressed = False self.move_pos = QPoint(0, 0) self.add = 0 self.angle = 0 self.downloading = False self.menu = QMenu(self) self.set_action = self.top.tray.set_action self.exit_action = self.top.tray.exit_action self.download_action = QAction(QIcon('image/download.png'), '下载', self) self.download_action.triggered.connect(self.download) self.menu.addActions( [self.set_action, self.download_action, self.exit_action]) def paintEvent(self, p): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.translate(37.5, 38) painter.rotate(self.angle) painter.translate(-37.5, -38) painter.drawPixmap(12, 13, 50, 50, self.pix) def event(self, e): # 鼠标移进移出 if e.type() == QEvent.Enter: self.setCursor(Qt.PointingHandCursor) self.top.right_frame.scale_state = 1 elif e.type() == QEvent.Leave: self.setCursor(Qt.ArrowCursor) if self.top.right_frame.like_label.width() == 40: self.top.right_frame.scale_delay = 50 self.top.right_frame.scale_state = -1 return super().event(e) def contextMenuEvent(self, e): self.menu.exec_(self.mapToGlobal(e.pos())) def mousePressEvent(self, e): self.pressed = True self.move_pos = e.pos() def mouseReleaseEvent(self, e): self.pressed = False if self.handle: self.handle = False else: if e.button() == 1: self.switch() def switch(self, type_=False): if not self.downloading: self.father.abort = False self.add = 1 self.downloading = True self.setToolTip('点击取消') self.top.set.api_choose.setEnabled(False) self.top.set.category_choose.setEnabled(False) Thread(target=self.process_download).start() elif not self.father.abort and not type_: # 停止 self.father.abort = True def mouseMoveEvent(self, e): if self.pressed: self.handle = True self.top.position = [ self.top.position[0] + e.x() - self.move_pos.x(), self.top.position[1] + e.y() - self.move_pos.y() ] self.top.setGeometry(*self.top.position, *self.top.size_) def process_download(self): # 开始下载 try: self.top.next_wall() except: # 无论什么错误都忽略 pass # 下载完毕 self.downloading = False self.setToolTip('来点好玩的') self.add = -1 self.father.step_time = 0 if self.top.config['play_what'] == '网络': self.top.set.api_choose.setEnabled(True) self.top.set.category_choose.setEnabled(True) if not self.father.abort and self.top.config['play_what'] != '本地': self.set_.emit() self.father.abort = False self.father.process_signal.emit(0) self.top.right_frame.reload_pix() if self.top.api.name + '_' + str( self.top.api.current_id) in self.top.data['download_list']: self.download_action.setIcon(QIcon('image/cancel_download.png')) self.download_action.setText('删除') else: self.download_action.setIcon(QIcon('image/download.png')) self.download_action.setText('下载') def download(self): try: if self.top.api.current_id and self.top.config['directory'] != 0: if self.download_action.text() == '下载': copyfile( 'image/wall.jpg', join( self.top.config['directory'], self.top.api.name + '_' + str(self.top.api.current_id) + '.jpg')) self.top.data['download_list'].append( self.top.api.name + '_' + str(self.top.api.current_id)) self.top.dump_data('data') self.download_action.setIcon( QIcon('image/cancel_download.png')) self.download_action.setText('删除') else: remove( join( self.top.config['directory'], self.top.api.name + '_' + str(self.top.api.current_id) + '.jpg')) self.top.data['download_list'].remove( self.top.api.name + '_' + str(self.top.api.current_id)) self.top.dump_data('data') self.download_action.setIcon(QIcon('image/download.png')) self.download_action.setText('下载') except: return
def mouseMoveEvent(self, event: QMouseEvent): if self.scene() is None: return cursor = self.cursor().shape() if self.grab_start is not None: move_x = self.grab_start.x() - event.pos().x() self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + move_x) if self.move_y_with_drag: move_y = self.grab_start.y() - event.pos().y() self.verticalScrollBar().setValue( self.verticalScrollBar().value() + move_y) self.grab_start = event.pos() return if self.separation_area_moving: y_sep = self.mapToScene(event.pos()).y() y = self.sceneRect().y() h = self.sceneRect().height() if y < y_sep < y + h: self.scene().draw_sep_area(y_sep, show_symbols=True) self.sep_area_moving.emit(y_sep) elif self.is_pos_in_separea(self.mapToScene(event.pos())): self.setCursor(Qt.SplitVCursor) elif cursor == Qt.SplitVCursor and self.has_horizontal_selection: self.unsetCursor() if self.selection_area.finished and not self.selection_area.resizing: pos = self.mapToScene(event.pos()) roi_edge = self.selection_area.get_selected_edge( pos, self.transform()) if roi_edge is None: if (cursor == Qt.SplitHCursor and self.has_horizontal_selection) \ or (cursor == Qt.SplitVCursor and not self.has_horizontal_selection): self.unsetCursor() return elif roi_edge == 0 or roi_edge == 1: if self.has_horizontal_selection: self.setCursor(Qt.SplitHCursor) else: self.setCursor(Qt.SplitVCursor) if event.buttons() == Qt.LeftButton and self.selection_area.resizing: if self.selection_area.selected_edge == 0: start = self.mapToScene(event.pos()) self.__set_selection_area(x=start.x(), y=start.y()) if self.has_horizontal_selection: self.scroll_mouse(start.x()) return if self.selection_area.selected_edge == 1: start = QPoint(self.selection_area.x, self.selection_area.y) end = self.mapToScene(event.pos()) self.__set_selection_area(w=end.x() - start.x(), h=end.y() - start.y()) if self.has_horizontal_selection: self.scroll_mouse(end.x()) return if self.mouse_press_pos is None: return self.mouse_pos = event.pos() if event.buttons( ) == Qt.LeftButton and not self.selection_area.finished: start = self.mapToScene(self.mouse_press_pos) end = self.mapToScene(self.mouse_pos) self.__set_selection_area(w=end.x() - start.x(), h=end.y() - start.y()) if self.has_horizontal_selection: self.scroll_mouse(end.x())
def mouseMoveEvent(self, event): delta = QPoint(event.globalPos() - self.prev_pos) self.move(self.x() + delta.x(), self.y() + delta.y()) self.prev_pos = event.globalPos()
class Settings(object): l = logging.getLogger('Settings') def __init__(self, fileName = 'shadow.ini'): self.fileName = fileName self.tzIdx = 0 self.mainWindowSize = QSize(1200, 700) self.mainWindowPos = QPoint(240, 200) def load(self): self.l.debug('Loading local settings from {}'.format(self.fileName)) config = configparser.ConfigParser() config.read(self.fileName) if config.has_section('common'): commonSettings = config['common'] self.tzIdx = int(commonSettings.get('tz', 0)) # load main window position and size if config.has_section('mainWindow'): windowSettings = config['mainWindow'] # read position pos = windowSettings.get('pos', '{},{}'.format(self.mainWindowPos.x(), self.mainWindowPos.y())).split(',') self.mainWindowPos = QPoint(int(pos[0]), int(pos[1])) # read size size = windowSettings.get('size', '{},{}'.format(self.mainWindowSize.width(), self.mainWindowSize.height())).split(',') self.mainWindowSize = QSize(int(size[0]), int(size[1])) def dump(self, channel): self.l.debug('Saving local settings ...') config = configparser.ConfigParser() config.add_section('common') config.set('common', 'tz', str(self.tzIdx)) config.add_section('mainWindow') config.set('mainWindow', 'pos', '{},{}'.format(self.mainWindowPos.x(), self.mainWindowPos.y())) config.set('mainWindow', 'size', '{},{}'.format(self.mainWindowSize.width(), self.mainWindowSize.height())) config.write(channel) def save(self): with open(self.fileName, 'w') as configfile: self.dump(configfile) def setMainWindowPos(self, pos): self.mainWindowPos = pos def setMainWindowSize(self, size): self.mainWindowSize = size def getMainWindowPos(self): return self.mainWindowPos def getMainWindowSize(self): return self.mainWindowSize def getTzIndex(self): return self.tzIdx def setTzIdx(self, idx): self.tzIdx = idx
def move(self, target: QtCore.QPoint): self.move_animation.setStartValue(self.getGeometry()) self.move_animation.setEndValue( QtCore.QRect(target.x(), target.y(), self._width, self._height)) self.move_animation.start()
def paintEvent(self, event): painter = QPainter(self) painter.setPen(self.pen) painter.setBrush(self.brush) if self.antialiased: painter.setRenderHint(QPainter.Antialiasing) angle_step = 360 / self.n_states painter.save() #Save_1. Save the state of the system (push matrix) painter.translate(self.dist_center.x(), self.dist_center.y()) # go to the center of the render area painter.rotate(-180) #to start painting from the left side of the circle (clockwise) #center of the circumference where through we are going to paint our states x = self.dist_radius * math.cos(0) y = self.dist_radius * math.sin(0) for h in range(self.n_states): rot = angle_step * h # each state is equidistant from the others. We paint them in circles painter.save() #Save_2 painter.rotate(rot) #now our system is pointing to the next state to be drawn painter.translate(x,y) #now our origin is in the center of the next state to be drawn #if the state is active, fill it green if self.machine.getState(h).isActive(): painter.setBrush(self.greenGradientBrush) painter.drawEllipse(QPoint(0,0), self.state_radius, self.state_radius) #draw the new state #global position of transformed coordinates (before any transformation, origin at top-left corner) gx = painter.worldTransform().map(QPoint(0,0)).x() gy = painter.worldTransform().map(QPoint(0,0)).y() self.machine.getState(h).setPos(gx, gy) #store the center of the state without any transformation applied # text transformation. Our origin is still in the center of the current state painter.save() #Save_3 painter.rotate(180) #making the text go vertical painter.rotate(-rot) #undoing the rotation made for painting the state. No the text is horizontal font = painter.font(); font.setPixelSize(self.state_radius*.4); painter.setFont(font); rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2) painter.drawText(rect, Qt.AlignCenter, self.machine.getState(h).getName()); painter.restore() #Restore_3 #end text transformation painter.restore() #Restore_2 painter.restore() #Restore_1. Restore the state of the system (pop matrix) #drawing transitions. Line between states painter.save() # Save_4 pptv = QTransform() #Define a new transformation. Needed to rotate the system along other axis than Z pptv.translate(0, self.height()) #We are now at the bottom-left corner of the screen pptv.rotate(-180, Qt.XAxis) #Rotate along the X-axis so now we are in a typical cartesian system. painter.setTransform(pptv) #Apply the transformation states = self.machine.getStates() for state in states: transitions = state.getTransitions() for transition in transitions: #get the center of the origin and destination states in our current system state orig = QPoint(state.getPos()[0], state.getPos()[1]) end = QPoint(self.machine.getState(transition.getStateEnd()).getPos()[0], self.machine.getState(transition.getStateEnd()).getPos()[1]) # get those coordinates without transformation orig2 = QPoint(painter.worldTransform().map(orig)) end2 = QPoint(painter.worldTransform().map(end)) #get the angle between states centers and the horizon angle = math.atan2(end2.y() - orig2.y(), end2.x() - orig2.x()) #get the coordinates of the starting point of the transition (it starts in the bound of the state, not in the center) newX = self.state_radius * math.cos(angle) + orig2.x() newY = self.state_radius * math.sin(angle) + orig2.y() #now the transition starts at the border, not in the center orig2.setX(newX) orig2.setY(newY) #same for the destination state angle2 = math.atan2(orig2.y() - end2.y(), orig2.x() - end2.x()) newX2 = self.state_radius * math.cos(angle2) + end2.x() newY2 = self.state_radius * math.sin(angle2) + end2.y() end2.setX(newX2) end2.setY(newY2) #draw the line between the origin and destination states painter.drawLine(orig2, end2) #get the start and the end of the transition untransformed init = QPoint(painter.worldTransform().map(orig2)) end = QPoint(painter.worldTransform().map(end2)) #store that info transition.setOrig(init.x(), init.y()) transition.setDest(end.x(), end.y()) transition.setAngle(angle) painter.restore() #Restore_4 #Appliying style to the transitions painter.setPen(QPen(QColor(Qt.gray), 3)) for state in self.machine.getStates(): for transition in state.getTransitions(): #get the start and end coordinates of the transition i = QPoint(transition.getOrig()[0], transition.getOrig()[1]) o = QPoint(transition.getDest()[0], transition.getDest()[1]) painter.drawPolyline(i, o) #Drawing the arrow at the end of the transition painter.save() #Save_5 painter.setPen(QPen(QColor(Qt.gray), 2)) painter.translate(transition.getDest()[0],transition.getDest()[1]) #Go to the end of the transition painter.rotate(90 - transition.getAngle()*180/math.pi) #Rotate to point in the direction of the transition #coordinates of the arrow (triangle) a = QPoint(0,0) b = QPoint(-5,10) c = QPoint(5,10) #coordinates of the arrow untransformed a1 = painter.worldTransform().map(a) b1 = painter.worldTransform().map(b) c1 = painter.worldTransform().map(c) #Drawin the actual arrow pointer = QPolygon([a,b,c]) painter.drawPolygon(pointer) painter.restore() #Restore_5 #For the animation of the transition painter.save() #Save_6 if transition.isActive(): #if the current transition is the active one the wave function will be running, so it's updating the canvas painter.setPen(QPen(QColor(Qt.green), 3)) painter.drawPolyline(i,o) painter.setPen(QPen(QColor(Qt.gray), 3)) painter.drawPolyline(self.poly(self.pts)) #Draw the arrow in the active state (red arrow) painter.setBrush(QBrush(QColor(255, 0, 0))) painter.setPen(QPen(QColor(Qt.red), 2)) pointer = QPolygon([a1,b1,c1]) painter.drawPolygon(pointer) #Ball that follows the line animation for x, y in self.pts: painter.drawEllipse(QRectF(self.pts[0][0] - 4, self.pts[0][1] - 4, 8, 8)) painter.restore() #Restore_6 #Painting the text of the transition painter.save() #Save_7 pptv = QTransform() painter.setPen(QPen(QColor(Qt.black), 3)) #get the middle point of the transition middleX = (transition.getOrig()[0] + transition.getDest()[0]) /2 middleY = (transition.getOrig()[1] + transition.getDest()[1]) /2 pptv.translate(middleX, middleY) #translate to that point painter.setTransform(pptv) #apply the transformation font = painter.font(); font.setPixelSize(self.state_radius*.2); painter.setFont(font); rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2) name = str(transition.getId())+ '. ' + transition.getName() painter.drawText(rect, Qt.AlignCenter, name) painter.restore() #Restore_7 #paint the actual canvas painter.setPen(self.palette().dark().color()) painter.setBrush(Qt.NoBrush) painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))
def mouseMoveEvent(self, event): if self.mIsPressed: appNewPos = QPoint() appNewPos.setX(QCursor.pos().x() - self.mXDiff) appNewPos.setY(QCursor.pos().y() - self.mYDiff) self.move(appNewPos.x(), appNewPos.y())
class GLWidget(QOpenGLWidget): xRotationChanged = pyqtSignal(int) yRotationChanged = pyqtSignal(int) zRotationChanged = pyqtSignal(int) zoomChanged = pyqtSignal(int) def __init__(self, parent=None): super(GLWidget, self).__init__(parent) self.model = None self.xRot = 1700 self.yRot = 2850 self.zRot = 0 self.lastPos = QPoint() self.r_back = self.g_back = self.b_back = 0 self.plotdata = [] self.plotlen = 16000 # Where we are centering. self.xcenter = 0.0 self.ycenter = 0.0 self.zcenter = 0.0 # Where the eye is self.distance = 10.0 # Field of view in y direction self.fovy = 30.0 # Position of clipping planes. self.near = 0.1 self.far = 1000.0 # View settings self.perspective = 0 self.lat = 0 self.minlat = -90 self.maxlat = 90 # does not show HUD by default self.hud = Hud() # self.hud.show("stuff") # add a 100ms timer to poll linuxcnc stats self.timer = QTimer() self.timer.timeout.connect(self.update) self.timer.start(100) def getOpenglInfo(self): info = """ Vendor: {0} Renderer: {1} OpenGL Version: {2} Shader Version: {3} """.format( GL.glGetString(GL.GL_VENDOR), GL.glGetString(GL.GL_RENDERER), GL.glGetString(GL.GL_VERSION), GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION) ) return info def minimumSizeHint(self): return QSize(50, 50) def sizeHint(self): return QSize(400, 400) def winfo_width(self): return self.geometry().width() def winfo_height(self): return self.geometry().height() def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle self.xRotationChanged.emit(angle) self.update() def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle self.yRotationChanged.emit(angle) self.update() def setZRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.zRot: self.zRot = angle self.zRotationChanged.emit(angle) self.update() def setZoom(self, depth): self.distance = depth self.update() def zoomin(self): self.distance = self.distance / 1.1 if self.distance < 600: self.distance = 600 self.update() def zoomout(self): self.distance = self.distance * 1.1 if self.distance > 5600: self.distance = 5600 self.update() def set_latitudelimits(self, minlat, maxlat): """Set the new "latitude" limits for rotations.""" if maxlat > 180: return if minlat < -180: return if maxlat <= minlat: return self.maxlat = maxlat self.minlat = minlat def initializeGL(self): # basic_lighting GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, (1, -1, .5, 0)) GL.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, (.2, .2, .2, 0)) GL.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, (.6, .6, .4, 0)) GL.glLightfv(GL.GL_LIGHT0 + 1, GL.GL_POSITION, (-1, -1, .5, 0)) GL.glLightfv(GL.GL_LIGHT0 + 1, GL.GL_AMBIENT, (.0, .0, .0, 0)) GL.glLightfv(GL.GL_LIGHT0 + 1, GL.GL_DIFFUSE, (.0, .0, .4, 0)) GL.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE, (1, 1, 1, 0)) GL.glDisable(GL.GL_CULL_FACE) GL.glEnable(GL.GL_LIGHTING) GL.glEnable(GL.GL_LIGHT0) GL.glEnable(GL.GL_LIGHT0 + 1) GL.glDepthFunc(GL.GL_LESS) GL.glEnable(GL.GL_DEPTH_TEST) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() def paintGL(self): GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) GL.glLoadIdentity() GL.glTranslated(0.0, 0.0, -10.0) GL.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0) GL.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0) GL.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0) # draw Objects GL.glPushMatrix() # Protect our matrix w = self.winfo_width() h = self.winfo_height() GL.glViewport(0, 0, w, h) # Clear the background and depth buffer. GL.glClearColor(self.r_back, self.g_back, self.b_back, 0.) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GLU.gluPerspective(self.fovy, float(w) / float(h), self.near, self.far) if 0: # Now translate the scene origin away from the world origin GL.glMatrixMode(GL.GL_MODELVIEW) mat = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX) GL.glLoadIdentity() GL.glTranslatef(-self.xcenter, -self.ycenter, -(self.zcenter + self.distance)) GL.glMultMatrixd(mat) else: GLU.gluLookAt(self.xcenter, self.ycenter, self.zcenter + self.distance, self.xcenter, self.ycenter, self.zcenter, 0., 1., 0.) GL.glMatrixMode(GL.GL_MODELVIEW) # Call objects redraw method. self.drawObjects() GL.glFlush() # Tidy up GL.glPopMatrix() # Restore the matrix def drawObjects(self, *args): if self.winfo_width() == 1: return if self.model is None: return self.model.traverse() # current coords: world # the matrices tool2view, work2view, and world2view # transform from tool/work/world coords to viewport coords # if we want to draw in tool coords, we need to do # "tool -> view -> world" (since the current frame is world) # and if we want to draw in work coords, we need # "work -> view -> world". For both, we need to invert # the world2view matrix to do the second step view2world = invert(self.world2view.t) # likewise, for backplot, we want to transform the tooltip # position from tool coords (where it is [0,0,0]) to work # coords, so we need tool -> view -> work # so lets also invert the work2view matrix view2work = invert(self.work2view.t) # since backplot lines only need vertexes, not orientation, # and the tooltip is at the origin, getting the tool coords # is easy tx, ty, tz = self.tool2view.t[12:15] # now we have to transform them to the work frame wx = tx * view2work[0] + ty * view2work[4] + tz * view2work[8] + view2work[12] wy = tx * view2work[1] + ty * view2work[5] + tz * view2work[9] + view2work[13] wz = tx * view2work[2] + ty * view2work[6] + tz * view2work[10] + view2work[14] # wx, wy, wz are the values to use for backplot # so we save them in a buffer if len(self.plotdata) == self.plotlen: del self.plotdata[:self.plotlen / 10] point = [wx, wy, wz] if not self.plotdata or point != self.plotdata[-1]: self.plotdata.append(point) # now lets draw something in the tool coordinate system # GL.glPushMatrix() # matrixes take effect in reverse order, so the next # two lines do "tool -> view -> world" # GL.glMultMatrixd(view2world) # GL.glMultMatrixd(self.tool2view.t) # do drawing here # cylinder normally goes to +Z, we want it down # GL.glTranslatef(0,0,-60) # GLU.gluCylinder(self.q1, 20, 20, 60, 32, 16) # back to world coords # GL.glPopMatrix() # we can also draw in the work coord system GL.glPushMatrix() # "work -> view -> world" GL.glMultMatrixd(view2world) GL.glMultMatrixd(self.work2view.t) # now we can draw in work coords, and whatever we draw # will move with the work, (if the work is attached to # a table or indexer or something that moves with # respect to the world # just a test object, sitting on the table # GLU.gluCylinder(self.q2, 40, 20, 60, 32, 16) # draw head up display if (hasattr(self.hud, "draw")): self.hud.draw() # draw backplot GL.glDisable(GL.GL_LIGHTING) GL.glLineWidth(2) GL.glColor3f(1.0, 0.5, 0.5) GL.glBegin(GL.GL_LINE_STRIP) for p in self.plotdata: GL.glVertex3f(*p) GL.glEnd() GL.glEnable(GL.GL_LIGHTING) GL.glColor3f(1, 1, 1) GL.glLineWidth(1) GL.glDisable(GL.GL_BLEND) GL.glDepthFunc(GL.GL_LESS) # back to world again GL.glPopMatrix() def plotclear(self): del self.plotdata[:self.plotlen] def resizeGL(self, width, height): side = min(width, height) if side < 0: return GL.glViewport((width - side) // 2, (height - side) // 2, side, side) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0) GL.glMatrixMode(GL.GL_MODELVIEW) def mousePressEvent(self, event): self.lastPos = event.pos() def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.setXRotation(self.xRot + 8 * dy) self.setYRotation(self.yRot + 8 * dx) elif event.buttons() & Qt.RightButton: self.setXRotation(self.xRot + 8 * dy) self.setZRotation(self.zRot + 8 * dx) self.lastPos = event.pos() def mouseDoubleClickEvent(self, event): if event.button() & Qt.RightButton: self.plotclear() def wheelEvent(self, event): # Use the mouse wheel to zoom in/out a = event.angleDelta().y() / 200 if a < 0: self.zoomout() else: self.zoomin() event.accept() def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle
def __drawTool(self, pos, mark): """ Private method to perform a draw operation depending of the current tool. @param pos widget coordinate to perform the draw operation at (QPoint) @param mark flag indicating a mark operation (boolean) @return flag indicating a successful draw (boolean) """ self.__unMark() if mark: self.__endPos = QPoint(pos) drawColor = self.MarkColor img = self.__markImage else: drawColor = self.penColor() img = self.__image start = QPoint(*self.__imageCoordinates(self.__startPos)) end = QPoint(*self.__imageCoordinates(pos)) painter = QPainter(img) painter.setPen(drawColor) painter.setCompositionMode(self.__compositingMode) if self.__curTool == self.Line: painter.drawLine(start, end) elif self.__curTool in [ self.Rectangle, self.FilledRectangle, self.RectangleSelection ]: left = min(start.x(), end.x()) top = min(start.y(), end.y()) right = max(start.x(), end.x()) bottom = max(start.y(), end.y()) if self.__curTool == self.RectangleSelection: painter.setBrush(QBrush(drawColor)) if self.__curTool == self.FilledRectangle: for y in range(top, bottom + 1): painter.drawLine(left, y, right, y) else: painter.drawRect(left, top, right - left, bottom - top) if self.__selecting: self.__selRect = QRect(left, top, right - left + 1, bottom - top + 1) self.__selectionAvailable = True self.selectionAvailable.emit(True) elif self.__curTool in [ self.Circle, self.FilledCircle, self.CircleSelection ]: r = max(abs(start.x() - end.x()), abs(start.y() - end.y())) if self.__curTool in [self.FilledCircle, self.CircleSelection]: painter.setBrush(QBrush(drawColor)) painter.drawEllipse(start, r, r) if self.__selecting: self.__selRect = QRect(start.x() - r, start.y() - r, 2 * r + 1, 2 * r + 1) self.__selectionAvailable = True self.selectionAvailable.emit(True) elif self.__curTool in [self.Ellipse, self.FilledEllipse]: r1 = abs(start.x() - end.x()) r2 = abs(start.y() - end.y()) if r1 == 0 or r2 == 0: return False if self.__curTool == self.FilledEllipse: painter.setBrush(QBrush(drawColor)) painter.drawEllipse(start, r1, r2) painter.end() if self.__curTool in [ self.Circle, self.FilledCircle, self.Ellipse, self.FilledEllipse ]: self.update() else: self.__updateRect(self.__startPos, pos) return True
class GLWidget(QOpenGLWidget): def __init__(self, parent=None): super(GLWidget, self).__init__(parent) midnight = QTime(0, 0, 0) random.seed(midnight.secsTo(QTime.currentTime())) self.object = 0 self.xRot = 0 self.yRot = 0 self.zRot = 0 self.image = QImage() self.bubbles = [] self.lastPos = QPoint() self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0) self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0) self.animationTimer = QTimer() self.animationTimer.setSingleShot(False) self.animationTimer.timeout.connect(self.animate) self.animationTimer.start(25) self.setAutoFillBackground(False) self.setMinimumSize(200, 200) self.setWindowTitle("Overpainting a Scene") def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle def setZRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.zRot: self.zRot = angle def initializeGL(self): self.gl = self.context().versionFunctions() self.gl.initializeOpenGLFunctions() self.object = self.makeObject() def mousePressEvent(self, event): self.lastPos = event.pos() def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.setXRotation(self.xRot + 8 * dy) self.setYRotation(self.yRot + 8 * dx) elif event.buttons() & Qt.RightButton: self.setXRotation(self.xRot + 8 * dy) self.setZRotation(self.zRot + 8 * dx) self.lastPos = event.pos() def paintEvent(self, event): self.makeCurrent() self.gl.glMatrixMode(self.gl.GL_MODELVIEW) self.gl.glPushMatrix() self.setClearColor(self.trolltechPurple.darker()) self.gl.glShadeModel(self.gl.GL_SMOOTH) self.gl.glEnable(self.gl.GL_DEPTH_TEST) #self.gl.glEnable(self.gl.GL_CULL_FACE) self.gl.glEnable(self.gl.GL_LIGHTING) self.gl.glEnable(self.gl.GL_LIGHT0) self.gl.glEnable(self.gl.GL_MULTISAMPLE) self.gl.glLightfv(self.gl.GL_LIGHT0, self.gl.GL_POSITION, (0.5, 5.0, 7.0, 1.0)) self.setupViewport(self.width(), self.height()) self.gl.glClear( self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT) self.gl.glLoadIdentity() self.gl.glTranslated(0.0, 0.0, -10.0) self.gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0) self.gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0) self.gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0) self.gl.glCallList(self.object) self.gl.glMatrixMode(self.gl.GL_MODELVIEW) self.gl.glPopMatrix() painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) for bubble in self.bubbles: if bubble.rect().intersects(QRectF(event.rect())): bubble.drawBubble(painter) self.drawInstructions(painter) painter.end() def resizeGL(self, width, height): self.setupViewport(width, height) def showEvent(self, event): self.createBubbles(20 - len(self.bubbles)) def sizeHint(self): return QSize(400, 400) def makeObject(self): list = self.gl.glGenLists(1) self.gl.glNewList(list, self.gl.GL_COMPILE) self.gl.glEnable(self.gl.GL_NORMALIZE) self.gl.glBegin(self.gl.GL_QUADS) self.gl.glMaterialfv(self.gl.GL_FRONT, self.gl.GL_DIFFUSE, (self.trolltechGreen.red()/255.0, self.trolltechGreen.green()/255.0, self.trolltechGreen.blue()/255.0, 1.0)) x1 = +0.06 y1 = -0.14 x2 = +0.14 y2 = -0.06 x3 = +0.08 y3 = +0.00 x4 = +0.30 y4 = +0.22 self.quad(x1, y1, x2, y2, y2, x2, y1, x1) self.quad(x3, y3, x4, y4, y4, x4, y3, x3) self.extrude(x1, y1, x2, y2) self.extrude(x2, y2, y2, x2) self.extrude(y2, x2, y1, x1) self.extrude(y1, x1, x1, y1) self.extrude(x3, y3, x4, y4) self.extrude(x4, y4, y4, x4) self.extrude(y4, x4, y3, x3) NumSectors = 200 for i in range(NumSectors): angle1 = (i * 2 * math.pi) / NumSectors x5 = 0.30 * math.sin(angle1) y5 = 0.30 * math.cos(angle1) x6 = 0.20 * math.sin(angle1) y6 = 0.20 * math.cos(angle1) angle2 = ((i + 1) * 2 * math.pi) / NumSectors x7 = 0.20 * math.sin(angle2) y7 = 0.20 * math.cos(angle2) x8 = 0.30 * math.sin(angle2) y8 = 0.30 * math.cos(angle2) self.quad(x5, y5, x6, y6, x7, y7, x8, y8) self.extrude(x6, y6, x7, y7) self.extrude(x8, y8, x5, y5) self.gl.glEnd() self.gl.glEndList() return list def quad(self, x1, y1, x2, y2, x3, y3, x4, y4): self.gl.glNormal3d(0.0, 0.0, -1.0) self.gl.glVertex3d(x1, y1, -0.05) self.gl.glVertex3d(x2, y2, -0.05) self.gl.glVertex3d(x3, y3, -0.05) self.gl.glVertex3d(x4, y4, -0.05) self.gl.glNormal3d(0.0, 0.0, 1.0) self.gl.glVertex3d(x4, y4, +0.05) self.gl.glVertex3d(x3, y3, +0.05) self.gl.glVertex3d(x2, y2, +0.05) self.gl.glVertex3d(x1, y1, +0.05) def extrude(self, x1, y1, x2, y2): self.setColor(self.trolltechGreen.darker(250 + int(100 * x1))) self.gl.glNormal3d((x1 + x2)/2.0, (y1 + y2)/2.0, 0.0) self.gl.glVertex3d(x1, y1, +0.05) self.gl.glVertex3d(x2, y2, +0.05) self.gl.glVertex3d(x2, y2, -0.05) self.gl.glVertex3d(x1, y1, -0.05) def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle def createBubbles(self, number): for i in range(number): position = QPointF(self.width()*(0.1 + 0.8*random.random()), self.height()*(0.1 + 0.8*random.random())) radius = min(self.width(), self.height())*(0.0125 + 0.0875*random.random()) velocity = QPointF(self.width()*0.0125*(-0.5 + random.random()), self.height()*0.0125*(-0.5 + random.random())) self.bubbles.append(Bubble(position, radius, velocity)) def animate(self): for bubble in self.bubbles: bubble.move(self.rect()) self.update() def setupViewport(self, width, height): side = min(width, height) self.gl.glViewport((width - side) // 2, (height - side) // 2, side, side) self.gl.glMatrixMode(self.gl.GL_PROJECTION) self.gl.glLoadIdentity() self.gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0) self.gl.glMatrixMode(self.gl.GL_MODELVIEW) def drawInstructions(self, painter): text = "Click and drag with the left mouse button to rotate the Qt " \ "logo." metrics = QFontMetrics(self.font()) border = max(4, metrics.leading()) rect = metrics.boundingRect(0, 0, self.width() - 2*border, int(self.height()*0.125), Qt.AlignCenter | Qt.TextWordWrap, text) painter.setRenderHint(QPainter.TextAntialiasing) painter.fillRect(QRect(0, 0, self.width(), rect.height() + 2*border), QColor(0, 0, 0, 127)) painter.setPen(Qt.white) painter.fillRect(QRect(0, 0, self.width(), rect.height() + 2*border), QColor(0, 0, 0, 127)) painter.drawText((self.width() - rect.width())/2, border, rect.width(), rect.height(), Qt.AlignCenter | Qt.TextWordWrap, text) def setClearColor(self, c): self.gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()) def setColor(self, c): self.gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())
def paintEvent(self, _event: QPaintEvent): if not self.crop or not self.resolution: return painter = QPainter(self) # Keep a backup of the transform and create a new one transform = painter.worldTransform() # Set scaling transform transform = transform.scale(self.width() / self.resolution.width(), self.height() / self.resolution.height()) # Compute the transform to flip the coordinate system on the x axis transform_flip = QTransform() if self.flip_x: transform_flip = transform_flip.translate(self.resolution.width(), 0.0) transform_flip = transform_flip.scale(-1.0, 1.0) # Small helper for tuple to QPoint def toqp(point): return QPoint(point[0], point[1]) # Starting from here we care about AA painter.setRenderHint(QPainter.Antialiasing) # Draw all the QR code results for res in self.results: painter.setWorldTransform(transform_flip * transform, False) # Draw lines between all of the QR code points pen = QPen(self.qr_outline_pen) if res in self.validator_results.result_colors: pen.setColor(self.validator_results.result_colors[res]) painter.setPen(pen) num_points = len(res.points) for i in range(0, num_points): i_n = i + 1 line_from = toqp(res.points[i]) line_from += self.crop.topLeft() line_to = toqp( res.points[i_n] if i_n < num_points else res.points[0]) line_to += self.crop.topLeft() painter.drawLine(line_from, line_to) # Draw the QR code data # Note that we reset the world transform to only the scaled transform # because otherwise the text could be flipped. We only use transform_flip # to map the center point of the result. painter.setWorldTransform(transform, False) font_metrics = painter.fontMetrics() data_metrics = QSize(font_metrics.horizontalAdvance(res.data), font_metrics.capHeight()) center_pos = toqp(res.center) center_pos += self.crop.topLeft() center_pos = transform_flip.map(center_pos) text_offset = QPoint(data_metrics.width(), data_metrics.height()) text_offset = text_offset / 2 text_offset.setX(-text_offset.x()) center_pos += text_offset padding = self.BG_RECT_PADDING bg_rect_pos = center_pos - QPoint(padding, data_metrics.height() + padding) bg_rect_size = data_metrics + (QSize(padding, padding) * 2) bg_rect = QRect(bg_rect_pos, bg_rect_size) bg_rect_path = QPainterPath() radius = self.BG_RECT_CORNER_RADIUS bg_rect_path.addRoundedRect(QRectF(bg_rect), radius, radius, Qt.AbsoluteSize) painter.setPen(self.bg_rect_pen) painter.fillPath(bg_rect_path, self.bg_rect_fill) painter.drawPath(bg_rect_path) painter.setPen(self.text_pen) painter.drawText(center_pos, res.data)