将 NetworkX 图嵌入 PyQT 小部件
Posted
技术标签:
【中文标题】将 NetworkX 图嵌入 PyQT 小部件【英文标题】:Embedding a NetworkX graph into PyQT widget 【发布时间】:2016-02-11 00:51:09 【问题描述】:我想将使用 NetworkX 创建的图表嵌入到 PyQT5 小部件中。我找到了一个使用 Matplotlib 的正弦函数示例,它运行良好,但我不知道如何使用 NetworkX 图表。
我的代码:
import sys
from PyQt5 import QtWidgets
from gt import Ui_MainWindow
import networkx as nx
import numpy as np
import pylab as P
import matplotlib.pyplot as plt
from networkx.algorithms import bipartite
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from numpy import arange, sin, pi
# example
class DrawSin(FigureCanvas):
def __init__(self, parent=None):
fig = Figure()
self.axes = fig.add_subplot(111)
self.axes.hold(False)
t = arange(0.0, 3.0, 0.01)
s = sin(2*pi*t)
self.axes.plot(t, s)
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
class Core(QtWidgets.QMainWindow):
def __init__(self):
super(Core, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
grid = QtWidgets.QGridLayout(self.ui.widget)
draw_sin = DrawSin(self.ui.widget)
grid.addWidget(draw_sin)
self.ui.widget.setFocus()
# my graph
class Test:
def graphb(self):
B = nx.Graph()
B.add_nodes_from([1, 2, 3, 4], bipartite=0)
B.add_nodes_from(['a', 'b', 'c', 'd', 'e'], bipartite=1)
B.add_edges_from([(1, 'a'), (2, 'c'), (3, 'd'), (3, 'e'), (4, 'e'), (4, 'd')])
X = set(n for n, d in B.nodes(data=True) if d['bipartite'] == 0)
Y = set(B) - X
X = sorted(X, reverse=True)
Y = sorted(Y, reverse=True)
pos = dict()
pos.update( (n, (1, i)) for i, n in enumerate(X) ) # put nodes from X at x=1
pos.update( (n, (2, i)) for i, n in enumerate(Y) ) # put nodes from Y at x=2
nx.draw(B, pos=pos, with_labels=True)
plt.show() # to remove
def main():
app = QtWidgets.QApplication(sys.argv)
test = Test()
test.graphb()
ui = Core()
ui.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
来自 Qt Designer 的 Ui 文件:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '.\graphtest.ui'
#
# Created by: PyQt5 UI code generator 5.4.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.widget = QtWidgets.QWidget(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth())
self.widget.setSizePolicy(sizePolicy)
self.widget.setObjectName("widget")
self.gridLayout.addWidget(self.widget, 0, 0, 1, 1)
self.listWidget = QtWidgets.QListWidget(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
self.listWidget.setSizePolicy(sizePolicy)
self.listWidget.setMaximumSize(QtCore.QSize(200, 16777215))
self.listWidget.setObjectName("listWidget")
self.gridLayout.addWidget(self.listWidget, 0, 1, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
我已经为 wxPython 找到了答案 here,但我不知道如何在 PyQT 中做到这一点。
【问题讨论】:
【参考方案1】:查看工作示例:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import networkx as nx
class PrettyWidget(QWidget):
NumButtons = ['plot1','plot2', 'plot3']
def __init__(self):
super(PrettyWidget, self).__init__()
font = QFont()
font.setPointSize(16)
self.initUI()
def initUI(self):
self.setGeometry(100, 100, 800, 600)
self.center()
self.setWindowTitle('S Plot')
grid = QGridLayout()
self.setLayout(grid)
self.createVerticalGroupBox()
buttonLayout = QVBoxLayout()
buttonLayout.addWidget(self.verticalGroupBox)
self.figure = plt.figure()
self.canvas = FigureCanvas(self.figure)
grid.addWidget(self.canvas, 0, 1, 9, 9)
grid.addLayout(buttonLayout, 0, 0)
self.show()
def createVerticalGroupBox(self):
self.verticalGroupBox = QGroupBox()
layout = QVBoxLayout()
for i in self.NumButtons:
button = QPushButton(i)
button.setObjectName(i)
layout.addWidget(button)
layout.setSpacing(10)
self.verticalGroupBox.setLayout(layout)
button.clicked.connect(self.submitCommand)
def submitCommand(self):
eval('self.' + str(self.sender().objectName()) + '()')
def plot1(self):
self.figure.clf()
ax1 = self.figure.add_subplot(211)
x1 = [i for i in range(100)]
y1 = [i**0.5 for i in x1]
ax1.plot(x1, y1, 'b.-')
ax2 = self.figure.add_subplot(212)
x2 = [i for i in range(100)]
y2 = [i for i in x2]
ax2.plot(x2, y2, 'b.-')
self.canvas.draw_idle()
def plot2(self):
self.figure.clf()
ax3 = self.figure.add_subplot(111)
x = [i for i in range(100)]
y = [i**0.5 for i in x]
ax3.plot(x, y, 'r.-')
ax3.set_title('Square Root Plot')
self.canvas.draw_idle()
def plot3(self):
self.figure.clf()
B = nx.Graph()
B.add_nodes_from([1, 2, 3, 4], bipartite=0)
B.add_nodes_from(['a', 'b', 'c', 'd', 'e'], bipartite=1)
B.add_edges_from([(1, 'a'), (2, 'c'), (3, 'd'), (3, 'e'), (4, 'e'), (4, 'd')])
X = set(n for n, d in B.nodes(data=True) if d['bipartite'] == 0)
Y = set(B) - X
X = sorted(X, reverse=True)
Y = sorted(Y, reverse=True)
pos = dict()
pos.update( (n, (1, i)) for i, n in enumerate(X) ) # put nodes from X at x=1
pos.update( (n, (2, i)) for i, n in enumerate(Y) ) # put nodes from Y at x=2
nx.draw(B, pos=pos, with_labels=True)
self.canvas.draw_idle()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)
app.setStyle(QStyleFactory.create("gtk"))
screen = PrettyWidget()
screen.show()
sys.exit(app.exec_())
"""
Modify base on:
http://***.com/questions/36086361/embed-matplotlib-in-pyqt-with-multiple-plot/36093604
"""
【讨论】:
以上是关于将 NetworkX 图嵌入 PyQT 小部件的主要内容,如果未能解决你的问题,请参考以下文章
将 Matplotlib 图形嵌入到小部件中 - PyQt5