Java 在顶角绘制按钮动画

Java Drawing Button Animations In Top Corner

我有一个 JFrame,其边框布局有两个 JPanel。框架南部的一个 JPanel 有一些 JButton(一个 n 数字),一个显示连接 - 4 板(这是用于 CS class)。出于某种奇怪的原因,我有一个奇怪的错误,按钮的动画显示在左上角。

这是一个很奇怪的错误,我不是挥杆专家 我想知道它是否与我有任何关系 运行 paint 方法([我认为 repaint()在另一个线程上)在一个 JPanelactionPerformed 在另一个 JPanel 中(我认为在另一个线程上)并且渲染中存在一些冲突或混乱。只是猜测。

这是一些 GUI 代码:

class Connect4GUI extends JFrame implements SetSpotInterface
{
    private Connect4 connect4;
    private Connect4PieceDisplay pieceDisplay;
    public static final String DEFAULT_TITLE = "Connect 4";
    //...
    public Connect4GUI( Connect4 connect4_, String title )
    {
        setTitle( title );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        connect4 = connect4_;
        pieceDisplay = new Connect4PieceDisplay( this );
        add( new Connect4ButtonDispencer( this ), BorderLayout.SOUTH );
        add( new Connect4PieceDisplay( this ), BorderLayout.CENTER );
        pack();
        setVisible( true );
    }
    public Connect4GUI( Connect4 connect4_ ) {
        this( connect4_, DEFAULT_TITLE );
    }
    public Connect4GUI() {
        this( new Connect4() );
    }
    //...
}

abstract class Connect4PanelComponent extends JPanel
{
    public static final Connect4GUI DEFAULT_DISPLAY_WINDOW = null;
    public final static Color DEFAULT_BACKROUND_COLOR = Color.YELLOW;
    Connect4GUI displayGUI;
    public Color backroundColor;
}

class Connect4PieceDisplay extends Connect4PanelComponent
{
    XY offsetScaler, offsetModifier, pixelOffset, spacingModifier, spacingPixelOffset;
    public final static XY DEFAULT_OFFSET_SCALER = new XY( 5, 5 );
    public final static XY DEFAULT_OFFSET_MODIFIER = new XY( 1, 1 );
    public final static XY DEFAULT_PIXEL_OFFSET = new XY( 6, 6 );
    public final static XY DEFAULT_SPACING_MODIFIER = new XY( 2, 2 );
    public final static XY DEFAULT_SPACING_PIXEL_OFFSET = new XY( 0, 0 );
    public Connect4PieceDisplay( Connect4GUI displayGUI_, XY offsetScaler_, XY offsetModifier_, XY pixelOffset_, XY spacingModifier_, XY spacingPixelOffset_, Color backroundColor_ )
    {
        super();
        displayGUI = displayGUI_;
        offsetScaler = offsetScaler_;
        offsetModifier = offsetModifier_;
        pixelOffset = pixelOffset_;
        spacingModifier = spacingModifier_;
        spacingPixelOffset = spacingPixelOffset_;
        backroundColor = backroundColor_;

        setOpaque( true );
        setBackground( backroundColor );
    }
    public Connect4PieceDisplay( Connect4GUI displayGUI_, XY offsetScaler_, XY offsetModifier_, XY pixelOffset_, XY spacingModifier_, XY spacingPixelOffset_ ) {
        this( displayGUI_, offsetScaler_, offsetModifier_, pixelOffset_, spacingModifier_, spacingPixelOffset_, DEFAULT_BACKROUND_COLOR );
    }
    public Connect4PieceDisplay( Connect4GUI displayGUI_, XY offsetScaler_, XY offsetModifier_, XY pixelOffset_, XY spacingModifier_ ) {
        this( displayGUI_, offsetScaler_, offsetModifier_, pixelOffset_, spacingModifier_, new XY( DEFAULT_SPACING_PIXEL_OFFSET ) );
    }
    public Connect4PieceDisplay( Connect4GUI displayGUI_, XY offsetScaler_, XY offsetModifier_, XY pixelOffset_ ) {
        this( displayGUI_, offsetScaler_, offsetModifier_, pixelOffset_, new XY( DEFAULT_SPACING_MODIFIER ) );
    }
    public Connect4PieceDisplay( Connect4GUI displayGUI_, XY offsetScaler_, XY offsetModifier_ ) {
        this( displayGUI_, offsetScaler_, offsetModifier_, new XY( DEFAULT_PIXEL_OFFSET ) );
    }
    public Connect4PieceDisplay( Connect4GUI displayGUI_, XY offsetScaler_ ) {
        this( displayGUI_, offsetScaler_, new XY( DEFAULT_OFFSET_MODIFIER ) );
    }
    public Connect4PieceDisplay( Connect4GUI displayGUI_ ) {
        this( displayGUI_, new XY( DEFAULT_OFFSET_SCALER ) );
    }
    public Connect4PieceDisplay() {
        this( DEFAULT_DISPLAY_WINDOW );
    }
    public void DefaultSetUpModifiers( int offset, int offsetModifier_, int spacing, int spacingPixel )
    {
        offsetScaler = new XY( offset, offset );
        offsetModifier = new XY( offsetModifier_, offsetModifier_ );
        pixelOffset = new XY( ( offset + 1 ), ( offset + 1 ) );
        spacingModifier = new XY( spacing, spacing );
        spacingPixelOffset = new XY( spacingPixel, spacingPixel );
    }
    public void paint( Graphics graphics )
    {
        final int X_DIMENTION = displayGUI.GetConnect4().dimentions.x;
        final int Y_DIMENTION = displayGUI.GetConnect4().dimentions.y;
        final int X_SPACING = ( getWidth() / X_DIMENTION );
        final int Y_SPACING = ( getHeight() / Y_DIMENTION );
        final int AMOUNT_OF_COLORS_IN_COLOR_MAP = displayGUI.colorMap.size();
        for( int i = 0; i < X_DIMENTION; ++i )
        {
            for( int j = 0; j < Y_DIMENTION; ++j )
            {
                final char CURRENT_SYMBOL = displayGUI.GetConnect4().GetSpot( i, j );
                for( int o = 0; o < AMOUNT_OF_COLORS_IN_COLOR_MAP; ++o )
                {
                    if( CURRENT_SYMBOL == displayGUI.colorMap.get( o ).GetSymbol() ) {
                        graphics.setColor( displayGUI.colorMap.get( o ).GetColor() );
                        break;
                    }
                }
                graphics.fillOval( AttainXOffset( i ), AttainYOffset( j ), AttainXSpacing(), AttainYSpacing() );
            }
        }
        repaint();
    }
    public int AttainXOffset( int x ) {
        final int X_SPACING = ( getWidth() / displayGUI.GetConnect4().dimentions.x );
        return ( ( X_SPACING / DEFAULT_OFFSET_SCALER.x ) + DEFAULT_PIXEL_OFFSET.x + ( X_SPACING * DEFAULT_OFFSET_MODIFIER.x * x ) );
    }
    public int AttainYOffset( int y ) {
        final int Y_SPACING = ( getHeight() / displayGUI.GetConnect4().dimentions.y );
        return ( ( Y_SPACING / DEFAULT_OFFSET_SCALER.y ) + DEFAULT_PIXEL_OFFSET.y + ( Y_SPACING * DEFAULT_OFFSET_MODIFIER.y * y ) );
    }
    public int AttainXSpacing() {
        final int X_SPACING = ( getWidth() / displayGUI.GetConnect4().dimentions.x );
        return ( ( X_SPACING / DEFAULT_SPACING_MODIFIER.x ) + DEFAULT_SPACING_PIXEL_OFFSET.x );
    }
    public int AttainYSpacing() {
        final int Y_SPACING = ( getHeight() / displayGUI.GetConnect4().dimentions.y );
        return ( ( Y_SPACING / DEFAULT_SPACING_MODIFIER.y ) + DEFAULT_SPACING_PIXEL_OFFSET.y );
    }
}

class Connect4ButtonDispencer extends Connect4PanelComponent implements ActionListener
{
    public final static String DEFAULT_BUTTON_MESSAGE = "";
    public final static int DEPTH_OF_BUTTON_GRID = 1;
    public JButton[] dispencerButtons;
    public String buttonMessage;
    public Connect4ButtonDispencer( Connect4GUI displayGUI_, Color backroundColor_, int amountOfDispencerButtons_, String buttonMessage_ )
    {
        super();
        displayGUI = displayGUI_;
        backroundColor = backroundColor_;
        buttonMessage = buttonMessage_;
        setLayout( new GridLayout( DEPTH_OF_BUTTON_GRID, amountOfDispencerButtons_ ) );
        dispencerButtons = DefaultSetUpDispencerButtons( amountOfDispencerButtons_ );
        buttonMessage = buttonMessage_;
        setOpaque( true );
        setBackground( backroundColor );
    }
    public Connect4ButtonDispencer( Connect4GUI displayGUI_, Color backroundColor_, int amountOfDispencerButtons_ ) {
        this( displayGUI_, backroundColor_, amountOfDispencerButtons_, DEFAULT_BUTTON_MESSAGE );
    }
    public Connect4ButtonDispencer( Connect4GUI displayGUI_, Color backroundColor_ ) {
        this( displayGUI_, backroundColor_, displayGUI_.GetConnect4().dimentions.x );
    }
    public Connect4ButtonDispencer( Connect4GUI displayGUI_ ) {
        this( displayGUI_, DEFAULT_BACKROUND_COLOR );
    }
    public Connect4ButtonDispencer() {
        this( DEFAULT_DISPLAY_WINDOW );
    }
    public JButton[] DefaultSetUpDispencerButtons( int length )
    {
        dispencerButtons = new JButton[ length ];
        //What if I change something in between when I declare the array and the 'for' loop?//
        final int AMOUNT_OF_DISPENCER_BUTTONS = dispencerButtons.length;
        for( int i = 0; i < AMOUNT_OF_DISPENCER_BUTTONS; ++i )
        {
            dispencerButtons[ i ] = new JButton( ( buttonMessage + ( i + 1 ) ) );
            dispencerButtons[ i ].addActionListener( this );
            add( dispencerButtons[ i ] );
        }
        return dispencerButtons;
    }
    public void actionPerformed( ActionEvent event )
    {
        final int AMOUNT_OF_DISPENCER_BUTTONS = dispencerButtons.length;
        for( int i = 0; i < AMOUNT_OF_DISPENCER_BUTTONS; ++i )
        {
            System.out.println( "A" );
            if( dispencerButtons[ i ] == event.getSource() )
            {
                System.out.println( "B" );
                //...it could change dynamically especially when this is on a thread. #parinoi .//
                final int Y_DIMENTIONS = displayGUI.GetConnect4().dimentions.y;
                for( int j = ( Y_DIMENTIONS - 1 ); j >= 0; --j )
                {
                    if( displayGUI.GetConnect4().GetSpot( i, j ) == Connect4.EMPTY_SPOT )
                    {
                        displayGUI.GetConnect4().SetSpot( i, j, displayGUI.turnSymbol );
                        displayGUI.ChangeTurn();
                        break;
                    }
                }
                break;
            }
        }
    }
}

非常感谢对此问题的任何见解或帮助! :)

谢谢 - TFB :-)

  1. 不要从 paint(...) 中调用 repaint(),因为这会导致
    • 动画无法控制,
    • 对不适合的东西使用绘画方法。
  2. 您甚至不应该覆盖 paint,而应该覆盖 paintComponent。
  3. 这是个大问题:您必须在您的绘画重写中调用 super 的绘画方法。因此,如果您要覆盖 paintComponent,请在其中调用 super.paintComponent(...) 方法。