How to draw the graph correctly after changing it by clicking on the button? If I add any rendering methods to this code, the window stops opening at all.
#include <JuceHeader.h>
#include <juce_gui_basics/juce_gui_basics.h>
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
using namespace juce;
class Graph_logics
{
std::vector<std::vector<int>> adjacencyMatrix;
public:
Graph_logics() { adjacencyMatrix = std::vector<std::vector<int>>(); }
void addVertex();
void removeVertex(int vertex);
void addEdge(int source, int destination, int weight);
void removeEdge(int source, int destination);
void printAdjacencyMatrix();
auto getAdjacencyMatrix();
void DFS(int startVertex);
void BFS(int startVertex);
std::vector<int> Dijkstra(int startVertex);
};
void Graph_logics::addVertex()
{
int numVertices = adjacencyMatrix.size();
for (int i = 0; i < numVertices; i++) adjacencyMatrix[i].push_back(0);
adjacencyMatrix.push_back(std::vector<int>(numVertices + 1, 0));
}
void Graph_logics::removeVertex(int vertex)
{
int numVertices = adjacencyMatrix.size();
if (vertex >= numVertices) { std::cout << "Invalid vertex!" << std::endl; return; }
adjacencyMatrix.erase(adjacencyMatrix.begin() + vertex);
for (int i = 0; i < numVertices - 1; i++) adjacencyMatrix[i].erase(adjacencyMatrix[i].begin() + vertex);
}
void Graph_logics::addEdge(int source, int destination, int weight)
{
int numVertices = adjacencyMatrix.size();
if (source >= numVertices || destination >= numVertices) { std::cout << "Invalid vertices!" << std::endl; return; }
adjacencyMatrix[source][destination] = weight;
}
void Graph_logics::removeEdge(int source, int destination)
{
int numVertices = adjacencyMatrix.size();
if (source >= numVertices || destination >= numVertices) { std::cout << "Invalid vertices!" << std::endl; return; }
adjacencyMatrix[source][destination] = 0;
}
void Graph_logics::printAdjacencyMatrix()
{
int numVertices = adjacencyMatrix.size();
for (int i = 0; i < numVertices; i++)
{
for (int j = 0; j < numVertices; j++) std::cout << adjacencyMatrix[i][j] << " ";
std::cout << std::endl;
}
}
auto Graph_logics::getAdjacencyMatrix() { return adjacencyMatrix; }
void Graph_logics::DFS(int startVertex)
{
int numVertices = adjacencyMatrix.size();
std::vector<bool> visited(numVertices, false);
std::stack<int> stack;
visited[startVertex] = true;
stack.push(startVertex);
while (!stack.empty())
{
int currentVertex = stack.top();
stack.pop();
std::cout << currentVertex << " ";
for (int i = 0; i < numVertices; i++)
if (adjacencyMatrix[currentVertex][i] != 0 && !visited[i])
{
visited[i] = true;
stack.push(i);
}
}
}
void Graph_logics::BFS(int startVertex)
{
int numVertices = adjacencyMatrix.size();
std::vector<bool> visited(numVertices, false);
std::queue<int> queue;
visited[startVertex] = true;
queue.push(startVertex);
while (!queue.empty())
{
int currentVertex = queue.front();
queue.pop();
std::cout << currentVertex << " ";
for (int i = 0; i < numVertices; i++)
if (adjacencyMatrix[currentVertex][i] != 0 && !visited[i])
{
visited[i] = true;
queue.push(i);
}
}
}
std::vector<int> Graph_logics::Dijkstra(int startVertex)
{
int numVertices = adjacencyMatrix.size();
std::vector<int> distance(numVertices, std::numeric_limits<int>::max());
std::vector<bool> visited(numVertices, false);
distance[startVertex] = 0;
for (int count = 0; count < numVertices - 1; count++) {
int minDistance = std::numeric_limits<int>::max();
int minVertex = -1;
for (int v = 0; v < numVertices; v++)
if (!visited[v] && distance[v] <= minDistance) { minDistance = distance[v]; minVertex = v; }
if (minVertex == -1) break;
visited[minVertex] = true;
for (int v = 0; v < numVertices; v++)
if (!visited[v] && adjacencyMatrix[minVertex][v] != 0 &&
distance[minVertex] != std::numeric_limits<int>::max() &&
distance[minVertex] + adjacencyMatrix[minVertex][v] < distance[v]) {
distance[v] = distance[minVertex] + adjacencyMatrix[minVertex][v];
}
} return distance;
}
class GraphPaint : public juce::Component
{
Graph_logics* graph;
public:
GraphPaint(Graph_logics* graph) : graph(graph) {}
void paint(juce::Graphics& g) override
{
const int vertexRadius = 20;
const int startX = 150;
const int startY = 150;
const int padding = 100;
g.fillAll(juce::Colours::white);
auto adjacencyMatrix = graph->getAdjacencyMatrix();
int numVertices = adjacencyMatrix.size();
for (int i = 0; i < numVertices; i++)
{
int x = startX + i * padding;
int y = startY;
// Draw vertex
g.setColour(juce::Colours::blue);
g.drawEllipse(x - vertexRadius, y - vertexRadius, vertexRadius * 2, vertexRadius * 2, 2);
// Draw vertex label
g.setColour(juce::Colours::black);
juce::String vertexLabel = juce::String(i);
g.drawText(vertexLabel, x - vertexRadius, y - vertexRadius, vertexRadius * 2, vertexRadius * 2,
juce::Justification::centred, true);
for (int j = 0; j < numVertices; j++)
{
int weight = adjacencyMatrix[i][j];
if (weight != 0)
{
int destX = startX + j * padding;
int destY = startY;
// Draw edge
g.setColour(juce::Colours::black);
g.drawLine(x, y + vertexRadius, destX, destY - vertexRadius, 2);
// Draw edge weight
g.setColour(juce::Colours::red);
juce::String weightLabel = juce::String(weight);
int textX = (x + destX) / 2;
int textY = (y + destY) / 2;
g.drawText(weightLabel, textX - vertexRadius, textY - vertexRadius, vertexRadius * 2, vertexRadius * 2,
juce::Justification::centred, true);
}
}
}
}
};
class Creative_1Application : public juce::JUCEApplication
{
public:
Creative_1Application() {}
const juce::String getApplicationName() override { return ProjectInfo::projectName; }
const juce::String getApplicationVersion() override { return ProjectInfo::versionString; }
bool moreThanOneInstanceAllowed() override { return true; }
void initialise(const juce::String& commandLine) override
{
mainWindow.reset(new MainWindow(getApplicationName()));
mainWindow->setVisible(true);
mainWindow->setContentNonOwned(new GraphPaint(nullptr), true);
}
void shutdown() override { mainWindow = nullptr; }
void systemRequestedQuit() override { quit(); }
void anotherInstanceStarted(const juce::String& commandLine) override {}
private:
class MainWindow : public juce::DocumentWindow, public juce::Button::Listener
{
private:
Graph_logics* graph;
GraphPaint* graphPaint;
public:
MainWindow(juce::String name) : juce::DocumentWindow(name, juce::Colours::lightgrey, juce::DocumentWindow::closeButton), graph(nullptr), graphPaint(nullptr)
{
centreWithSize(800, 600);
setVisible(true);
button1 = new juce::TextButton();
button1->setButtonText("Add Vertex");
button1->setBounds(5, 30, 100, 30);
button1->addListener(this);
addAndMakeVisible(button1);
button2 = new juce::TextButton();
button2->setButtonText("Delete Vertex");
button2->setBounds(5, 60, 100, 30);
button2->addListener(this);
addAndMakeVisible(button2);
button3 = new juce::TextButton();
button3->setButtonText("Add Edge");
button3->setBounds(5, 90, 100, 30);
button3->addListener(this);
addAndMakeVisible(button3);
button4 = new juce::TextButton();
button4->setButtonText("Delete Edge");
button4->setBounds(5, 120, 100, 30);
button4->addListener(this);
addAndMakeVisible(button4);
button5 = new juce::TextButton();
button5->setButtonText("BFS");
button5->setBounds(5, 150, 100, 30);
button5->addListener(this);
addAndMakeVisible(button5);
button6 = new juce::TextButton();
button6->setButtonText("DFS");
button6->setBounds(5, 180, 100, 30);
button6->addListener(this);
addAndMakeVisible(button6);
button7 = new juce::TextButton();
button7->setButtonText("TSP");
button7->setBounds(5, 210, 100, 30);
button7->addListener(this);
addAndMakeVisible(button7);
graph = new Graph_logics();
graphPaint = new GraphPaint(graph);
}
void resized() override
{
graphPaint->setBounds(getLocalBounds());
}
void buttonClicked(juce::Button* button) override
{
if (button == button1) { graph->addVertex(); }
else if (button == button2) { graph->removeVertex(1); }
else if (button == button3) { graph->addEdge(1, 1, 1); }
else if (button == button4) { graph->removeEdge(1, 1); }
else if (button == button5) { graph->BFS(1); }
else if (button == button6) { graph->DFS(1); }
else if (button == button7) { /* Обработка нажатия на кнопку "TSP" */ }
repaint();
}
void paint(juce::Graphics& g) override
{
juce::DocumentWindow::paint(g); // Вызов родительского метода paint()
if (graphPaint != nullptr)
graphPaint->paint(g); // Отрисовка графа
resized(); // Обновление размеров компонента
}
void closeButtonPressed() override { juce::JUCEApplication::getInstance()->systemRequestedQuit(); }
private:
juce::TextButton* button1;
juce::TextButton* button2;
juce::TextButton* button3;
juce::TextButton* button4;
juce::TextButton* button5;
juce::TextButton* button6;
juce::TextButton* button7;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainWindow)
};
std::unique_ptr<MainWindow> mainWindow;
};
START_JUCE_APPLICATION(Creative_1Application)
