Commit f6d96021 authored by Francois Mares's avatar Francois Mares
Browse files

developpement clics graphs

parent 53bce9a4
......@@ -173,7 +173,7 @@ class Description:
else:
descr+="}"
# flesches
# fleches
fleches_elem = set(self._obj[self._obj.objets,self._obj.objets])
if complet:
func = lambda x,y : self._obj({x},{y})
......
......@@ -25,6 +25,9 @@ class Parameters():
ExportAsDialog_BG='white'
HIGHLIGHTCOLOR_BUTTON="#649BB4"
# COLORS
BUTTON_COLOR="#FFFFFF"
"""
///////////////////// NetworkX
"""
......
"""entry point for Tkinter Window with OpenGL]
"""
from itertools import product
from enum import Enum, unique
from tkinter import TOP, X, YES, BOTH, \
Frame, Label
......@@ -18,6 +19,88 @@ from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationTool
import networkx as nx
@unique
class LayoutAlgo(Enum):
Random=nx.random_layout
Graphviz=nx.nx_agraph.graphviz_layout
class NodeSelector:
"""
À associer à un évènement (clic de la sourie)
__call__ est alors appelée
"""
_pos=None
_axis=None
_data=None
_drawnAnnotations = {}
_G=None
_selection=[]
def __init__(self, pos, G, axis=None):
self._G=G
self._pos=pos
self._axis= axis
x, y, annotes = [], [], []
for key in pos:
d = pos[key]
annotes.append(key)
x.append(d[0])
y.append(d[1])
self._data = list(zip(x, y, annotes))
def __call__(self, event):
if event.inaxes:
clickX = event.xdata
clickY = event.ydata
print("event:",dir(event),event.key)
if self._axis is None or self._axis==event.inaxes:
distances = []
smallest_x_dist = float('inf')
smallest_y_dist = float('inf')
for x,y,a in self._data:
if abs(clickX-x)<=smallest_x_dist and abs(clickY-y)<=smallest_y_dist :
dx, dy = x - clickX, y - clickY
distances.append((dx*dx+dy*dy,x,y, a) )
smallest_x_dist=abs(clickX-x)
smallest_y_dist=abs(clickY-y)
print(distances[-1])
if distances:
distances.sort() # to select the nearest node
distance, x, y, annote = distances[0]
# self.drawAnnote(event.inaxes, x, y, annote)
self.select(event.inaxes, annote)
def select(self, axis, node):
if node in self._selection:
self._selection.remove(node)
nx.set_node_attributes(self._G, {node: "red"}, name="fillcolor")
#self._G.nodes[int(node)]['color']='red'
else:
self._selection.append(node)
nx.set_node_attributes(self._G, {node: "blue"}, name="fillcolor")
#self._G.nodes[int(node)]['color']='blue'
axis.cla()
nx.draw_networkx(self._G, ax=axis, pos=self._pos)
axis.figure.canvas.draw()
# print(self._G.nodes(data=True))
def drawAnnote(self, axis, x, y, annote):
if (x, y) in self._drawnAnnotations:
markers = self._drawnAnnotations[(x, y)]
for m in markers:
m.set_visible(not m.get_visible())
axis.figure.canvas.draw()
else:
t = axis.text(x, y, "%s" % (annote), )
m = axis.scatter([x], [y], marker='d', c='r', zorder=100)
self._drawnAnnotations[(x, y)] = (t, m)
axis.figure.canvas.draw()
class PlotFrame(Frame):
_controller=None
......@@ -25,6 +108,9 @@ class PlotFrame(Frame):
_plot=None
_canvas=None
_layoutAlgo=LayoutAlgo.Random
_pos=None
def __init__(self, parent, controller, *args, **kwargs):
assert controller
Frame.__init__(self, parent, *args, **kwargs)
......@@ -44,9 +130,12 @@ class PlotFrame(Frame):
self._plot=f.add_subplot(111)
self._plot.cla()
nx.draw_networkx(G, ax=self._plot, pos=nx.random_layout(G), node_color='r', edge_color='b')
self._pos=nx.random_layout(G)
nx.set_node_attributes(G, {n:"blue" for n in G.nodes(data=True)}, name="color")
nx.draw_networkx(G, ax=self._plot, pos=self._pos, edge_color='r')
self._canvas = FigureCanvasTkAgg(f, master=self)
self._canvas.mpl_connect('button_press_event', NodeSelector(self._pos, G))
self._canvas.draw()
toolbar = NavigationToolbar2Tk(self._canvas, self, pack_toolbar=False)
......@@ -57,10 +146,16 @@ class PlotFrame(Frame):
def setGraph(self, graph:nx.Graph):
self._plot.cla()
# generate node positions
if callable(getattr(graph,"check_planarity",None)) and graph.check_planarity()[0]:
nx.draw_networkx(graph, ax=self._plot, pos=nx.planar_layout(graph))
self._pos=nx.planar_layout(graph)
else:
nx.draw_networkx(graph, ax=self._plot, pos=nx.random_layout(graph))
self._pos=nx.random_layout(graph)
print(self._pos)
# draw
nx.draw_networkx(graph, ax=self._plot, pos=self._pos)
self._canvas.draw()
......@@ -68,6 +163,7 @@ class PlotFrame(Frame):
class GraphGenerator:
"""
Static
......
......@@ -6,6 +6,7 @@ from tkinter import TOP, YES, BOTH, X, \
from Parameters import parameters
from tk.OutilsFrame import OutilsFrame
from tk.ObjetsFrame import ObjetsFrame
from tk.MetriquesFrame import MetriquesFrame
from plot.PlotFrame import PlotFrame
......@@ -20,6 +21,7 @@ class MainWindow:
_outFrame=None
_objFrame=None
def getPlotFrame(self): return self._plotFrame
_metFrame=None
_glApp=None
_menu=None
......@@ -53,19 +55,25 @@ class MainWindow:
self._frame.columnconfigure(0, weight=3, minsize=500)
self._frame.columnconfigure(1, weight=1, minsize=200)
self._frame.columnconfigure(2, weight=2, minsize=200)
self._frame.rowconfigure(0, weight=1, minsize=300)
self._frame.rowconfigure(0, weight=1, minsize=20)
self._frame.rowconfigure(1, weight=1, minsize=20)
# Plot frame
self._plotFrame=PlotFrame(self._frame, self._controller)
self._plotFrame.grid(row=0, column=0, sticky="nesw")
self._plotFrame.grid(row=0, column=0, rowspan=2, sticky="nesw")
# Outils frame
self._outFrame = OutilsFrame(self._frame, self._controller)
self._outFrame.grid(row=0, column=1, sticky="nesw")
# Metriques frame
self._metFrame=MetriquesFrame(self._frame)
self._metFrame.grid(row=1, column=1, sticky="nesw")
# Objets frame
self._objFrame = ObjetsFrame(self._frame, self._controller, self)
self._objFrame.grid(row=0, column=2, sticky="nesw")
self._objFrame.grid(row=0, column=2, rowspan=2, sticky="nesw")
self._objFrame.registerSelection(self._metFrame)
def _initMenu(self):
......
"""
Définition de l'espace de droite
"""
from pandas import DataFrame
from tkinter import TOP, X, NO, W, Y, YES, BOTH, RIGHT, VERTICAL, \
Frame, Label, Menu
from tkinter.ttk import Treeview, Style, Scrollbar
from Model import Description
from tk.InformFrame import InformFrame
from tk.Factory import *
from tk.ObjetsFrameCallable import ObjetsFrameCallable
from plot.PlotFrame import GraphGenerator
class MetriquesFrame(Frame, ObjetsFrameCallable):
_informFrame=None
def __init__(self, parent, *args, **kwargs):
Frame.__init__(self, parent, *args, **kwargs)
self.columnconfigure(0, weight=1, minsize=100)
self.columnconfigure(1, minsize=16)#default value of scrollbar width
self.rowconfigure(0, minsize=20)
self.rowconfigure(1, weight=4, minsize=100)
self._initFrame()
def _initFrame(self):
factory.buildSectionLabel(self,"Métriques").grid(row=0, column=0, columnspan = 2, sticky="nwe")
# INFORM
self._informFrame=InformFrame(self)
self._informFrame.grid(row=2, columnspan = 2, column=0, sticky="nesw")
def informObjectSelected(self, uid, obj:object):
print(uid)
self._informFrame.setText(f"{uid}: {obj}")
......@@ -4,8 +4,8 @@ from Model import ModelObjects
from GrapheDeComposition import MGC
from re import split, findall
from tkinter import TOP, BOTTOM, LEFT, RIGHT, X, VERTICAL, \
LabelFrame, Frame, Label, Text, Scrollbar, Button
from tkinter import TOP, BOTTOM, LEFT, RIGHT, X, VERTICAL, END, INSERT, \
LabelFrame, Frame, Label, Text, Scrollbar, Button, Spinbox
from tkinter.ttk import Combobox
......@@ -106,8 +106,8 @@ class BuildObjectFrame(Frame):
morphismes=self._textMorphismes.getList(),
identifications=self._textIdentifications.getList(),
nom = None)
self._validateButton=Button(self, text="Générer", command=generate)
self._validateButton.grid(row=0, column=0, sticky="e")
self._validateButton=Button(self, text="Générer", bg=parameters.BUTTON_COLOR, command=generate)
self._validateButton.grid(row=0, column=0, columnspan=2, sticky="ew")
class LabelText(LabelFrame):
......@@ -146,13 +146,37 @@ class LabelText(LabelFrame):
return self._text.get("1.0",'end-1c')
class ObjectLabelText(LabelText):
_genererSpinbox=None
_genererButton=None
def __init__(self, parent, *args, **kwargs):
LabelText .__init__(self, parent, name="Objets", description="ex: 1,2,3...", *args, **kwargs)
LabelText.__init__(self, parent, name="Objets", description="ex: 1,2,3...", *args, **kwargs)
self.add_generateur()
def getList(self):
return [x for x in split('[,\n]', self.getText()) if x]
def add_generateur(self, min:int=1, max:int=150, default:int=10):
self._genererSpinbox=Spinbox(self, from_=min, to=max)
self._genererSpinbox.grid(row=2, column=0, sticky="nw")
self._genererSpinbox.delete('0', END)
self._genererSpinbox.insert(INSERT,str(default))
def generate():
i=int(self._genererSpinbox.get())
if i >=min and i<=max:
txt=""
for point in range(min,i+1):
txt+=str(point)+','
txt=txt[:-1]
self._text.delete('1.0', END)
self._text.insert(INSERT,txt)
else:
print(f"Erreur: {i} n'appartient pas à [{min},{max}].")
self._genererButton=Button(self, text="Ajouter", command=generate)
self._genererButton.grid(row=2, column=1, sticky="nw")
class MorphismeLabelText(LabelText):
def __init__(self, parent, *args, **kwargs):
......
......@@ -11,6 +11,7 @@ from Model import Description
from tk.InformFrame import InformFrame
from tk.Factory import *
from tk.ObjetsFrameCallable import ObjetsFrameCallable
from plot.PlotFrame import GraphGenerator
......@@ -84,6 +85,14 @@ class ObjetsFrame(Frame, ModelCallable):
self._informFrame=InformFrame(self)
self._informFrame.grid(row=2, columnspan = 2, column=0, sticky="nesw")
_selectionRegistered=[]
def registerSelection(self, ofCallable:ObjetsFrameCallable):
self._selectionRegistered.append(ofCallable)
def callRegisteredSelection(self, uid, obj:object):
for registered in self._selectionRegistered:
registered.informObjectSelected(uid, obj)
"""
GETTERS
"""
......@@ -96,7 +105,7 @@ class ObjetsFrame(Frame, ModelCallable):
def getFolder(self, class_name:str):
return self.getIfExist(self._folders, class_name)
def getSelectedObjects(self):
def getSelectedObjects(self)->list:
curItems = self._tree.selection()
sel=[]
for i in curItems:
......@@ -152,16 +161,18 @@ class ObjetsFrame(Frame, ModelCallable):
BIND FUNCTIONS/MENU FUNCTIONS
"""
def objectSelection(self, event):
curItems = self._tree.selection()
curItems = self.getSelectedObjects()
text=""
for i in curItems:
if self._tree.parent(i):
item=self._tree.item(i)
text+= (str(item['text'])+" : <"+
str(item['values'][0])+"> "+
str(item['values'][1])+"\n"
)
item=self._tree.item(i)
text+= (str(item['text'])+" : <"+
str(item['values'][0])+"> "+
str(item['values'][1])+"\n"
)
self._informFrame.setText(text)
if curItems:
uid=int(curItems[0])
self.callRegisteredSelection(uid, self._controller.getModel().getObject(uid))
def objectDelete(self, event):
pass
......
class ObjetsFrameCallable:
"""
A surcharger
Permet de s'enregistrer pour recevoir des notifications
d'une instance ObjetsFrame.
"""
def informObjectAdded(self, uid, obj:object):
pass
......@@ -19,7 +19,7 @@ class OutilsFrame(Frame):
self._controller=controller
self.columnconfigure(0, weight=1, minsize=100)
self.rowconfigure(0, minsize=20)
self.rowconfigure(1, weight=1, minsize=100)
self.rowconfigure(1, weight=1)
self._initFrame()
def _initFrame(self):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment