[英]How can I restore the state of an AdapterViewFlipper in a Fragment?
[英]How can I restore the state of my GUI to its original appearance?
我用Java編寫了一個GUI,用於使用2D圖形的吉他和弦查找器應用程序。 該程序在畫布上打開.jpg圖像。 然后它將每個單獨的音符(音柱之間的空格)繪制為帶有音符名稱的橢圓。 該程序允許用戶通過改變和弦的各個音符的顏色,從工具欄中選擇和弦顯示在指板上的和弦。 但是,每當用戶選擇新的和弦時,不會刪除前一個和弦。 我怎樣才能解決這個問題? 這是我的一些代碼(該程序超過1000行代碼)。
public class Fretboard extends JFrame implements ActionListener{
public static void main(String[] args) {
JFrame frame = new Fretboard();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
// Variables to be used throughout the program
ImagePanel imageSrc;
// Declare fonts to be used
Font font1 = new Font("SansSerif", Font.BOLD, 18); // Font to be used for notes with # or b
Font chordFont = new Font("SansSerif", Font.BOLD, 50); // Font for the name of the chord displayed
Font font = new Font("SansSerif", Font.BOLD, 20); // Font to be used for whole note
int h = 40, w = 26, x = 695, y = 254;
// Declare the note variables
// First string
Ellipse2D E1 = new Ellipse2D.Double(x, y-110, w, h); // E note, open 1st string
Ellipse2D F1 = new Ellipse2D.Double(x, y, w, h); // F note, 1st string, 1st fret
Ellipse2D fSharp1 = new Ellipse2D.Double(x, y+125, w, h); // F#/Gb note, 1st string, 2nd fret
Ellipse2D G1 = new Ellipse2D.Double(x+2, y+240, w, h); // G note, 1st string, 3rd fret
/**
* Create the menu bar and set title
*/
public Fretboard() {
// Change the title of the window
setTitle("Fretboard Chord Finder");
// Create a menu bar where user will be given choice of chords
JMenuBar mb = new JMenuBar();
setJMenuBar(mb);
JMenu menu = new JMenu("Chords");
// Add names of chords to the menu
JMenuItem mi = new JMenuItem("A Major");
mi.addActionListener(this);
menu.add(mi);
mi = new JMenuItem("A Minor");
mi.addActionListener(this);
menu.add(mi);
Container cp = this.getContentPane();
cp.setLayout(new FlowLayout());
imageSrc = new ImagePanel();
cp.add(imageSrc);
}
/**
* Obtain the user's chord selection from the chord menu
*/
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if("A Major".equals(command))
paintAMajor();
if("A Minor".equals(command))
paintAMinor();
}
/**
* Displays the notes for the A Major chord when the user selects
* "A Major" from the toolbar.
*/
public void paintAMajor() {
// Declare local variables
Graphics g = getGraphics();
Graphics2D g2 = (Graphics2D) g;
// Display the name of the chord
g2.drawString("A Major Chord", 40, 150);
g2.drawString("Notes: A, C#, E", 40, 180);
// Display notes for the A Major chord
// Draw the E note on the open 1st string
// Change color to blue
g2.setColor(Color.red);
g2.draw(E1);
g2.fill(E1);
g2.setColor(Color.white);
g2.setFont(font);
g2.drawString("E", x+7, y-82);
// Change color back to red
g2.setColor(Color.red);
}
class ImagePanel extends JPanel {
BufferedImage image = null;
public ImagePanel() {
File fretBoardFile = new File("/Users/macbook/documents/workspace/Fretboard App/Gibson_Fretboard.jpg"); // The location of the fretboard image
// Open the image
try {
image = ImageIO.read(fretBoardFile);
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setPreferredSize(new Dimension(1280, 960));
}
/**
*
* @param bi
*/
public ImagePanel(BufferedImage bi) {
image = bi;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw the image of the fretboard on the canvas.
// Check to see if the image is available
if(image != null) {
g2.drawImage(image, 25, 0, null);
}
else
g2.drawRect(0, 0, getWidth()-1, getHeight()-1);
// Draw notes
// Draw the E note on the open 1st string
// Change color to blue
g2.setColor(Color.blue);
g2.draw(E1);
g2.fill(E1);
g2.setColor(Color.white);
g2.setFont(font);
g2.drawString("E", x+7, y-82);
// Change color back to blue
g2.setColor(Color.blue);
}
這是該計划的要點。 其他所有內容基本上都是每個音符或類似方法的位置以顯示和弦。 我被困住了,不知道如何修復這個程序。 這是我編程的第一個GUI。 請幫忙。 謝謝!
跳出來的第一件事就是使用getGraphics()
。 您應該避免使用此方法。
Java中的圖形是無狀態的。 也就是說,用於渲染組件的Graphics
上下文在循環之間不保證是相同的。 您不應該保持對Graphics
上下文的引用。
所有繪畫都應該在組件paint
方法的上下文中完成,最好是JComponent#paintComponent
,因為paint
方法是acomplex方法,做了很多重要的工作,你真的不想復制。
我會創建一種和弦的“模型”,每個實例都能夠自己繪制它。 然后我會創建一個能夠畫出音品和和弦的視圖。
以示例更新
這是一個概念證明的例子。 假設吉他弦從5(叢林)開始到0(最小)。
我不是音樂家,我沒有節拍或節奏,所以我可能犯了一些根本性的錯誤。
public class TestFretBoard {
public static void main(String[] args) {
new TestFretBoard();
}
public TestFretBoard() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ChordsPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ChordsPane extends JPanel {
public ChordsPane() {
setLayout(new BorderLayout());
FretPane fretPane = new FretPane();
fretPane.setChord(new AChord());
add(fretPane);
}
}
public static interface FretBoard {
public Rectangle getFretBounds(int index);
public GuitarString getGuitarString(int index);
public GuitarString[] getGuitarStrings(int... index);
}
public static class FretPane extends JPanel implements FretBoard {
private static final Point BOARD_OFFSET = new Point(9, 9);
private static final int BOARD_WIDTH = 84;
private static final Rectangle[] FRET_BOUNDS = {
new Rectangle(BOARD_OFFSET.x, 20, BOARD_WIDTH, 68 - 20),
new Rectangle(BOARD_OFFSET.x, 71, BOARD_WIDTH, 113 - 71),
new Rectangle(BOARD_OFFSET.x, 116, BOARD_WIDTH, 153 - 116),
new Rectangle(BOARD_OFFSET.x, 156, BOARD_WIDTH, 189 - 156),
new Rectangle(BOARD_OFFSET.x, 192, BOARD_WIDTH, 222 - 192),
new Rectangle(BOARD_OFFSET.x, 225, BOARD_WIDTH, 254 - 225),
new Rectangle(BOARD_OFFSET.x, 257, BOARD_WIDTH, 289 - 257),
new Rectangle(BOARD_OFFSET.x, 287, BOARD_WIDTH, 312 - 287),
new Rectangle(BOARD_OFFSET.x, 315, BOARD_WIDTH, 338 - 315),
new Rectangle(BOARD_OFFSET.x, 341, BOARD_WIDTH, 364 - 341),
new Rectangle(BOARD_OFFSET.x, 367, BOARD_WIDTH, 389 - 367),
new Rectangle(BOARD_OFFSET.x, 392, BOARD_WIDTH, 412 - 392),};
private static final GuitarString[] GUITAR_STRINGS = {
new GuitarString(85 - BOARD_OFFSET.x, 1),
new GuitarString(72 - BOARD_OFFSET.x, 1),
new GuitarString(58 - BOARD_OFFSET.x, 1),
new GuitarString(43 - BOARD_OFFSET.x, 2),
new GuitarString(29 - BOARD_OFFSET.x, 2),
new GuitarString(15 - BOARD_OFFSET.x, 2),};
private BufferedImage background;
private Chord chord;
public FretPane() {
try {
background = ImageIO.read(new File("fretboard02.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
}
public Chord getChord() {
return chord;
}
public void setChord(Chord chord) {
this.chord = chord;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (background != null) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
Chord chord = getChord();
if (chord != null) {
g2d.translate(x, y);
chord.paint(this, g2d);
g2d.translate(-x, -y);
}
}
g2d.dispose();
}
@Override
public Rectangle getFretBounds(int index) {
Rectangle bounds = null;
if (index >= 0 && index < FRET_BOUNDS.length) {
bounds = FRET_BOUNDS[index];
}
return bounds;
}
@Override
public GuitarString getGuitarString(int index) {
GuitarString gs = null;
if (index >= 0 && index < GUITAR_STRINGS.length) {
gs = GUITAR_STRINGS[index];
}
return gs;
}
@Override
public GuitarString[] getGuitarStrings(int... indices) {
List<GuitarString> strings = new ArrayList<GuitarString>(indices.length);
for (int index : indices) {
strings.add(getGuitarString(index));
}
return strings.toArray(new GuitarString[strings.size()]);
}
}
public static class GuitarString {
private int x;
private int width;
public GuitarString(int x, int width) {
this.x = x;
this.width = width;
}
public int getX() {
return x;
}
public int getWidth() {
return width;
}
}
public interface Chord {
public String getName();
public void paint(FretBoard board, Graphics2D g2d);
}
public abstract class AbstractChord implements Chord {
public abstract int[] getFrets();
public abstract GuitarString[] getGuitarStrings(FretBoard board, int fret);
@Override
public void paint(FretBoard board, Graphics2D g2d) {
for (int fret : getFrets()) {
Rectangle fretBounds = board.getFretBounds(fret);
// Guitar Strings start at 5 (thickest) to 0 (smallest)
GuitarString[] guitarStrings = getGuitarStrings(board, fret);
int y = fretBounds.y + (fretBounds.height / 2);
g2d.setColor(Color.RED);
Ellipse2D dot = new Ellipse2D.Float(0, 0, 10, 10);
for (GuitarString gs : guitarStrings) {
int x = ((gs.x + fretBounds.x) + (gs.width / 2)) - 5;
g2d.fill(getDot(dot, x, y - 5));
}
}
}
public Shape getDot(Ellipse2D dot, int x, int y) {
PathIterator pathIterator = dot.getPathIterator(AffineTransform.getTranslateInstance(x, y));
Path2D path = new Path2D.Float();
path.append(pathIterator, true);
return path;
}
}
public class AChord extends AbstractChord {
private int index;
@Override
public String getName() {
return "A";
}
@Override
public int[] getFrets() {
return new int[]{1};
}
@Override
public GuitarString[] getGuitarStrings(FretBoard board, int fret) {
GuitarString[] strings = new GuitarString[0];
switch (fret) {
case 1:
strings = board.getGuitarStrings(3, 2, 1);
break;
}
return strings;
}
}
}
圖像和用戶界面之間的映射有很多工作,你可以自己搞清楚,我打開了PhotoShop並手動測出了所有的點數。 如果你自己畫出音板,它會變得更容易。
基本概念圍繞“和弦”。 和弦有一個名字,可以畫自己。 我創建了一個簡單的Chord
接口抽象實現,它占用了大部分腿部工作,並且更容易創建新的和弦(因為你只需要為構成該和弦的每個音品提供音品和弦樂)
我也建議你仔細閱讀
一種方法是在每次調用paintComponent時從頭開始繪制所有內容。 無條件地繪制指板圖像,移動代碼在paintComponent中繪制選定的線,並根據某個變量繪制線,並使actionListner將該變量設置為選定的線。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.