简体   繁体   English

为什么即使调用repaint(),该程序也不能重绘applet的特定部分

[英]Why isn't this program repainting a certain part of an applet even when repaint() is called

This is a simple rock, paper, scissors appelet. 这是一个简单的石头,纸,剪刀的小食。 there are 3 variables keeping track of wins, losses, and ties. 有3个变量记录获胜,失败和平局。 Then there is a label that is meant to display them. 然后是一个用于显示它们的标签。 When I used the debugger the repaint method is being called so I don't understand why this portion of the applet isn't updating. 当我使用调试器时,将调用repaint方法,所以我不明白为什么小程序的这一部分没有更新。

import java.awt.Font;
import java.awt.Graphics;

import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JButton;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Random;

public class JRockPaperScissors extends JApplet {
    JLabel lblDescision = new JLabel("descision");
    JLabel lblWinner = new JLabel("winner");
    JLabel lblTally = new JLabel("tally");
    int tally_user = 0;
    int tally_comp = 0;
    int tally_ties = 0;



/**
 * Create the applet.
 */
public JRockPaperScissors() {
        setSize(500,500);
        getContentPane().setLayout(null);



    JLabel lblRockPaperScissors = new JLabel("Rock, Paper, Scissors");
    lblRockPaperScissors.setBounds(95, 50, 280, 48);
    getContentPane().add(lblRockPaperScissors);
    Font arial_1 = new Font("Arial", Font.BOLD, 25);
    lblRockPaperScissors.setFont(arial_1);

    JLabel lblChooseOneButton = new JLabel("Choose one button");
    lblChooseOneButton.setBounds(10, 93, 146, 25);
    getContentPane().add(lblChooseOneButton);
    Font arial_2 = new Font("Arial", Font.BOLD, 15);
    lblChooseOneButton.setFont(arial_2);

    JButton btnRock = new JButton("Rock");
    btnRock.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            determine_winner(0);
            repaint();
        }
    });
    btnRock.setBounds(166, 95, 89, 23);
    getContentPane().add(btnRock);

    JButton btnPaper = new JButton("Paper");
    btnPaper.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            determine_winner(1);
        }
    });
    btnPaper.setBounds(265, 95, 89, 23);
    getContentPane().add(btnPaper);

    JButton btnScissors = new JButton("Scissors");
    btnScissors.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            determine_winner(2);
        }
    });
    btnScissors.setBounds(361, 95, 89, 23);
    getContentPane().add(btnScissors);

    JLabel lblresults = new JLabel("------Results------");
    lblresults.setBounds(20, 114, 126, 25);
    getContentPane().add(lblresults);
    Font arial_3 = new Font("Arial", Font.BOLD, 15);
    lblresults.setFont(arial_3);

    lblDescision.setBounds(30, 150, 311, 14);
    getContentPane().add(lblDescision);

    lblWinner.setBounds(20, 175, 146, 14);
    getContentPane().add(lblWinner);

    JLabel lblTally = new JLabel("You:" + tally_user + "    Computer:" + tally_comp + 
            "    Ties:"+ tally_ties);
    lblTally.setBounds(20, 214, 201, 30);
    getContentPane().add(lblTally);


}

public void determine_winner(int user_choice){
    Random random = new Random();
    int computer_choice = random.nextInt(3);
    if(user_choice == 0 ){
        if(computer_choice ==0){
            lblDescision.setText("You picked Rock --- Computer picked Rock");
            lblWinner.setText("Winner: Tie");
            tally_ties +=1;
        }
        else if(computer_choice ==1){
            lblDescision.setText("You picked Rock --- Computer picked Paper");
            lblWinner.setText("Winner: Computer");
            tally_comp +=1;

        }
        else if(computer_choice ==2){
            lblDescision.setText("You picked Rock --- Computer picked Scissors");
            lblWinner.setText("Winner: You");
            tally_user +=1;

        }
    }
    else if(user_choice == 1){
        if(computer_choice ==0){
            lblDescision.setText("You picked Paper --- Computer picked Rock");
            lblWinner.setText("Winner: You");
            tally_user +=1;
        }
        else if(computer_choice ==1){
            lblDescision.setText("You picked Paper --- Computer picked Paper");
            lblWinner.setText("Winner: Tie");
            tally_ties +=1;
        }
        else if(computer_choice ==2){
            lblDescision.setText("You picked Paper --- Computer picked Scissors");
            lblWinner.setText("Winner: Computer");
            tally_comp +=1;
        }
    }
    else if(user_choice == 2){
        if(computer_choice ==0){
            lblDescision.setText("You picked Scissors --- Computer picked Rock");
            lblWinner.setText("Winner: Computer");
            tally_comp +=1;
        }
        else if(computer_choice ==1){
            lblDescision.setText("You picked Scissors --- Computer picked Paper");
            lblWinner.setText("Winner: You");
            tally_user +=1;
        }
        else if(computer_choice ==2){
            lblDescision.setText("You picked Scissors --- Computer picked Scissors");
            lblWinner.setText("Winner: Tie");
            tally_ties +=1;
        }
    }
revalidate();
repaint();
}

}
  • Issue number 1: You never change the text in the tally JLabel, lblTally. 问题编号1:您永远不会在提示标签JLabel lblTally中更改文本。 In other words, for the text in this JLabel and similar components to change you must specifically call, lblTally.setText(someNewString); 换句话说,要更改此JLabel和类似组件中的文本,必须专门调用lblTally.setText(someNewString);
  • Issue number 2: you're also shadowing the lblTally variable -- you're re-declaring and re-initializing the variable in the constructor, meaning that the JLabel object displayed in the GUI is not the same as the one that the class field refers to -- don't do this. 问题编号2:您还隐藏了lblTally变量-您在构造函数中重新声明并重新初始化了变量,这意味着GUI中显示的JLabel对象与class字段中的对象不同指-不要这样做。 Declare the variable and initialize it with a valid reference only once. 声明该变量,并仅使用一次有效的引用对其进行初始化。

Other side issues (issues not directly related to your problem) are: 其他附带问题(与您的问题不直接相关的问题)是:

  • You're using a null layout. 您正在使用null布局。 You will want to avoid use of null layout and use of setBounds(...) for component placement as this makes for very inflexible GUI's that while they might look good on one platform look terrible on most other platforms or screen resolutions and that are very difficult to update and maintain. 您将要避免使用空布局和使用setBounds(...)进行组件放置,因为这会导致非常不灵活的GUI,尽管它们在一个平台上看起来不错,但在大多数其他平台或屏幕分辨率上却看起来很糟糕,而且非常难以更新和维护。
  • Your applet has no init() method, the method that should get the applet up and running. 您的applet没有init()方法,该方法应该启动并运行applet。
  • There is no need to call revalidate() or repaint() after changing text in a JLabel. 在JLabel中更改文本后,无需调用revalidate()repaint()

In a nut shell, what you're doing is this: 简而言之,您正在做的是这样的:

import java.awt.event.ActionEvent;
import javax.swing.*;

public class JRockPaperEtc extends JApplet {
   private static final String FORMAT_TXT = "Tally: %03d";
   private int tally = 0;
   private JLabel lblTally = new JLabel(String.format(FORMAT_TXT, tally));

   @Override
   public void init() {
      JPanel mainPanel = new JPanel();

      // *** Variable Shadowing here
      JLabel lblTally = new JLabel("Tally: 000");
      mainPanel.add(lblTally);

      JButton button = new JButton(new AbstractAction("Push") {

         @Override
         public void actionPerformed(ActionEvent e) {
            tally++;
            // *** lblTally's text is never changed
         }
      });
      mainPanel.add(button);

      add(mainPanel);
   }
}

When you should be doing this: 当您应该这样做时:

import java.awt.event.ActionEvent;
import javax.swing.*;

public class JRockPaperEtc2 extends JApplet {
   private static final String FORMAT_TXT = "Tally: %03d";
   private int tally = 0;
   private JLabel lblTally = new JLabel(String.format(FORMAT_TXT, tally));

   @Override
   public void init() {
      JPanel mainPanel = new JPanel();

      // lblTally = new JLabel("Tally: 000"); // *** no shadowing
      mainPanel.add(lblTally);

      JButton button = new JButton(new AbstractAction("Push") {

         @Override
         public void actionPerformed(ActionEvent e) {
            tally++;
            lblTally.setText(String.format(FORMAT_TXT, tally));
            // *** lblTally's text is now changed
         }
      });
      mainPanel.add(button);

      add(mainPanel);
   }
}

Also, you ask: 另外,您问:

so what would you do instead of set bounds? 那么您会怎么做而不是设定界限? I'm just starting to learn gui apps so excuse me if this is a very in depth question. 我刚刚开始学习gui应用程序,所以请问这是一个非常深入的问题。

Instead of setBounds() , use layout managers to handle all the layout heavy lifting for you. 代替setBounds() ,使用布局管理器为您处理所有繁重的布局。 Google the Swing layout manager tutorial and have a look. Google Swing布局管理器教程,看看吧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM