Swing i kolorowanie JPanel w wątku

Swing i kolorowanie JPanel w wątku
CA
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 11 lat
0

Witam.
Zanim przejdę do kłopotów, chciałbym krótko scharakteryzować zadanie, które wykonuję. Napisałem program używając Appletu, który tworzył pewną strukturę przedstawioną poniżej:

Pierwszy ekran to ekran startowy. Na środku okna widoczne jest niebieskie koło. Styka się ono z czterema innymi kołami w kolorze czerwonym.
Zasada działania programu jest następująca:

  1. Na starcie tworzone są dwie ArrayListy z obiektami Point, które przechowują współrzędne x i y punktu.
  2. Jedna ArrayLista przechowuje pokolorowane punkty, a druga punkty do pokolorowania.
  3. Po dodaniu do pierwszej ArrayListy punktu niebieskiego (jako pokolorowanego), następuje dodanie kolejnych punktów do pokolorowania do drugiej ArrayListy (tych w kolorze czerwonym).
  4. Następuje uruchomienie wątku.
  5. W wątku losowany jest jeden element z listy elementów do pokolorowania i jest on kolorowany na zielono i dodawany do pierwszej ArrayListy elementów pokolorowanych, a także jest usuwany z listy elementów do pokolorowania.
  6. Następnie podobnie jak w przypadku punktu startowego wokół tego nowego pokolorowanego punktu tworzone są koła w kolorze czerwonym i dodawane do listy elementów do pokolorowania. Oczywiście jeśli nie ma ich na żadnej liście.
  7. Wątek wykonywany jest do momentu zapełnienia ekranu.
    user image

Tu widoczny efekt pokolorowania kilkunastu punktów:
user image

A teraz problem.
Po napisaniu Appletu chciałem przenieść całą logikę programu do Swinga. No i tu nie potrafię sobie poradzić z rysowaniem. Oto, co mam do tej pory. Wątek aktualnie nie posiada, żadnych opóźnień w rysowaniu i warunków, które były np. w Applecie, ale to wynika z faktu, że nie szło w ogóle rysowanie:

Kopiuj
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JPanel;

public class EdenPanel extends JPanel implements Runnable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -1418394043622693890L;
	int width;
	int height;
	int size;
	Color c;
	Thread th;

	Point startPoint;
	Point top;
	Point right;
	Point bottom;
	Point left;
	Point newPoint;

	public Point getStartPoint() {
		return startPoint;
	}

	public void setStartPoint(Point startPoint) {
		this.startPoint = startPoint;
	}

	public Point getTop() {
		return top;
	}

	public void setTop(Point top) {
		this.top = top;
	}

	public Point getRight() {
		return right;
	}

	public void setRight(Point right) {
		this.right = right;
	}

	public Point getBottom() {
		return bottom;
	}

	public void setBottom(Point bottom) {
		this.bottom = bottom;
	}

	public Point getLeft() {
		return left;
	}

	public void setLeft(Point left) {
		this.left = left;
	}

	public Point getNewPoint() {
		return newPoint;
	}

	public void setNewPoint(Point newPoint) {
		this.newPoint = newPoint;
	}

	public ArrayList<Point> emptyPoints = new ArrayList<Point>();
	public ArrayList<Point> coloredPoints = new ArrayList<Point>();

	public ArrayList<Point> getEmptyPoints() {
		return emptyPoints;
	}

	public void setEmptyPoints(ArrayList<Point> emptyPoints) {
		this.emptyPoints = emptyPoints;
	}

	public ArrayList<Point> getColoredPoints() {
		return coloredPoints;
	}

	public void setColoredPoints(ArrayList<Point> coloredPoints) {
		this.coloredPoints = coloredPoints;
	}

	public EdenPanel(int sizeX, int sizeY) {
		this.width = sizeX;
		this.height = sizeY;

		c = Color.BLUE;
		setBackground(Color.BLACK);
		setPreferredSize(new Dimension(width * 3 / 4, height));
	}

	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		c = Color.BLUE;
		g2.setColor(c);
		if (getRight() != null) {
			g2.fill(new Ellipse2D.Float.Float(startPoint.x, startPoint.y, size, size));
		}
		c = new Color(155, 38, 38);
		g2.setColor(c);
		if (getRight() != null) {
			g2.fill(new Ellipse2D.Float.Float(getRight().x, getRight().y, size, size));
		}
		if (getBottom() != null) {
			g2.fill(new Ellipse2D.Float.Float(getBottom().x, getBottom().y, size, size));
		}
		if (getLeft() != null) {
			g2.fill(new Ellipse2D.Float.Float(getLeft().x, getLeft().y, size, size));
		}
		if (getTop() != null) {
			g2.fill(new Ellipse2D.Float.Float(getTop().x, getTop().y, size, size));
		}
		c = new Color(74, 208, 17);
		g2.setColor(c);
		if (getNewPoint() != null) {
			g2.fill(new Ellipse2D.Float.Float(getNewPoint().x, getNewPoint().y, size, size));
		}
	}

	public void update(Graphics g) {
		paint(g);
	}

	public void paintFirstCell(int size) {
		this.size = size;
		startPoint = createStartPoint(width * 3 / 4, height);
		left = createLeftPoint(startPoint);
		right = createRightPoint(startPoint);
		top = createTopPoint(startPoint);
		bottom = createBottomPoint(startPoint);
		revalidate();
		repaint();

	}

	public Point createStartPoint(int windowSizeX, int windowSizeY) {
		startPoint = new Point();
		startPoint.x = windowSizeX / 2;
		startPoint.y = windowSizeY / 2;
		setStartPoint(startPoint);

		coloredPoints.add(startPoint);
		setColoredPoints(coloredPoints);

		return startPoint;
	}

	private Point createLeftPoint(Point p) {
		left = new Point();
		left.x = p.x - size;
		left.y = p.y;

		if (!emptyPoints.contains(left) && !coloredPoints.contains(left) && left.x > size) {
			emptyPoints.add(left);
			setLeft(left);
			return left;
		} else {
			return null;
		}
	}

	private Point createRightPoint(Point p) {
		right = new Point();
		right.x = p.x + size;
		right.y = p.y;

		if (!emptyPoints.contains(right) && !coloredPoints.contains(right) && right.x < width - size) {
			emptyPoints.add(right);
			setRight(right);
			return right;
		} else {
			return null;
		}
	}

	private Point createTopPoint(Point p) {
		top = new Point();
		top.x = p.x;
		top.y = p.y + size;

		if (!emptyPoints.contains(top) && !coloredPoints.contains(top) && top.y < height - size) {
			emptyPoints.add(top);
			setTop(top);
			return top;
		} else {
			return null;
		}
	}

	private Point createBottomPoint(Point p) {
		bottom = new Point();
		bottom.x = p.x;
		bottom.y = p.y + this.size;

		if (!emptyPoints.contains(bottom) && !coloredPoints.contains(bottom) && bottom.y > this.size) {
			emptyPoints.add(bottom);
			setBottom(bottom);
			return bottom;
		} else {
			return null;
		}
	}

	@Override
	public void run() {
		while (true) {
			createNewPoint(getStartPoint());
			left = createLeftPoint(getNewPoint());
			right = createRightPoint(getNewPoint());
			top = createTopPoint(getNewPoint());
			bottom = createBottomPoint(getNewPoint());
		}
	}

	private void createNewPoint(Point p) {
		// TODO Auto-generated method stub
		Random r = new Random();
		int index = r.nextInt(getEmptyPoints().size());
		setNewPoint(getEmptyPoints().get(index));
		getColoredPoints().add(getNewPoint());
		setColoredPoints(coloredPoints);
	}

	public void stopPainting() {
		//th.interrupt();
	}
}
edytowany 2x, ostatnio: Carter
init0
pokaż jeszcze klase w której uruchamiasz to na jakimś panelu albo framie
CA
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 11 lat
0

Klasa, w której uruchamiam:

Kopiuj
public class MainClass {
	private static final int WIDTH = 800;
	private static final int HEIGHT = 600;

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGUI();
			}
		});
	}

	private static void createAndShowGUI() {
		System.out.println("Created GUI on EDT? " + SwingUtilities.isEventDispatchThread());
		JFrame f = new JFrame("Eden Growth Model");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setLayout(new BorderLayout());
		f.setResizable(false);
		f.setPreferredSize(new Dimension(WIDTH, HEIGHT));

		EdenPanel edenPanel = new EdenPanel(WIDTH, HEIGHT);
		ControlPanel controlPanel = new ControlPanel(WIDTH, HEIGHT, edenPanel);

		f.add(edenPanel);
		f.add(controlPanel, BorderLayout.EAST);
		f.pack();
		f.setLocationRelativeTo(null);
		f.setVisible(true);
	}
}

ControlPanel:

Kopiuj
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;

public class ControlPanel extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = -6969280129122570471L;
	int width;
	int height;
	EdenPanel edenPanel;

	public ControlPanel(int sizeX, int sizeY, EdenPanel ep) {
		this.width = sizeX;
		this.height = sizeY;
		this.edenPanel = ep;

		setPreferredSize(new Dimension(width / 4, height));
		setBorder(BorderFactory.createLineBorder(Color.black));

		JLabel cellSizeLabel = new JLabel("Set size of single cell:");
		cellSizeLabel.setPreferredSize(new Dimension(width / 4 - 15, 20));

		JLabel cellsNumberLabel = new JLabel("Set number of cells:");
		cellsNumberLabel.setPreferredSize(new Dimension(width / 4 - 15, 20));

		JLabel growthSpeedLabel = new JLabel("Set the speed of growth");
		growthSpeedLabel.setPreferredSize(new Dimension(width / 4 - 15, 20));

		SpinnerModel cellSizeModel = new SpinnerNumberModel(5, 1, 20, 1);
		final JSpinner cellSizeSpinner = new JSpinner(cellSizeModel);
		cellSizeSpinner.setPreferredSize(new Dimension(width / 4 - 15, 20));

		int cellSize = (int) cellSizeSpinner.getValue();
		int maxCells = (int) ((width * height) / (Math.PI * cellSize / 2));
		SpinnerModel cellsNumberModel = new SpinnerNumberModel(maxCells, 1, maxCells, 1);
		final JSpinner cellsNumberSpinner = new JSpinner(cellsNumberModel);
		cellsNumberSpinner.setPreferredSize(new Dimension(width / 4 - 15, 20));

		final JSlider speedSlider = new JSlider(JSlider.HORIZONTAL, 0, 100, 1);
		speedSlider.setPreferredSize(new Dimension(width / 4 - 15, 20));

		final JButton clearButton = new JButton("Clear");
		clearButton.setName("clear");
		clearButton.setPreferredSize(new Dimension(width / 4 - 15, 30));
		clearButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JButton but = new JButton("Buttonik");
				edenPanel.add(but);
				edenPanel.validate();
				edenPanel.repaint();
			}
		});

		JButton startButton = new JButton("Start");
		startButton.setName("start");
		startButton.setPreferredSize(new Dimension(width / 4 - 15, 30));
		startButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JButton b = (JButton) e.getSource();
				
				if(b.getText().equals("Start")) {
					b.setText("Stop");
					cellSizeSpinner.setEnabled(false);
					cellsNumberSpinner.setEnabled(false);
					speedSlider.setEnabled(false);
					clearButton.setEnabled(false);
					int size = (int) cellSizeSpinner.getValue();
					edenPanel.paintFirstCell(size);					
				} else {
					b.setText("Start");
					cellSizeSpinner.setEnabled(true);
					cellsNumberSpinner.setEnabled(true);
					speedSlider.setEnabled(true);
					clearButton.setEnabled(true);
					edenPanel.stopPainting();
				}
			}
		});

		add(cellSizeLabel);
		add(cellSizeSpinner);
		add(Box.createHorizontalStrut(50));
		add(new JSeparator(SwingConstants.HORIZONTAL));
		add(Box.createHorizontalStrut(50));
		add(cellsNumberLabel);
		add(cellsNumberSpinner);
		add(Box.createHorizontalStrut(50));
		add(new JSeparator(SwingConstants.HORIZONTAL));
		add(Box.createHorizontalStrut(50));
		add(growthSpeedLabel);
		add(speedSlider);
		add(Box.createHorizontalStrut(50));
		add(new JSeparator(SwingConstants.HORIZONTAL));
		add(Box.createHorizontalStrut(50));
		add(startButton);
		add(Box.createHorizontalStrut(50));
		add(new JSeparator(SwingConstants.HORIZONTAL));
		add(Box.createHorizontalStrut(50));
		add(clearButton);
	}
}

Point:

Kopiuj
public class Point {
	int x;
	int y;

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}
}
edytowany 1x, ostatnio: Carter
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)