小弟目前在用Swing做一个桌面应用程序遇到一个问题就是JPanel的页面不能正常跳转。
比如下面的代码:else if ("确定出票" == ((JButton) btn).getName()) {
if (btn == e.getSource()) {
System.out.println("确定出票被点击了");
TvmFrame.getInstance().remove(StationCashTicket.getInstance());
TvmFrame.getInstance().remove(StationCardTicket.getInstance());
TvmFrame.getInstance().remove(PriceCardTicket.getInstance());
TvmFrame.getInstance().remove(PriceCashTicket.getInstance());
TvmFrame.getInstance().add(Ticketing.getInstance()); //始终不能正常的跳到这个页面
TvmFrame.getInstance().repaint();
if (sellingOneWayTicket.sellTickets()) {
System.out.println("开始压币");
coinModulServiceImpl.startManage();
coinModulServiceImpl.stopManage();
} else {
// 当机器出现故障出票失败时将硬币全部退出
coinModulServiceImpl.changeCoin(coinModulServiceImpl.get1NoOfCoin(),0);
coinModulServiceImpl.outCoin();//很多时候都如果出现问题的话都是直接跳到这个页面,上面红色字体的那个页面直接过了

}
} } else if ("重选站台" == ((JButton) btn).getName()) {按照逻辑应该是先跳到Ticketing这个页面然后根据sellingOneWayTicket.sellTickets()的执行过程跳到另外一个页面sellTickets的代码如下:
public boolean sellTickets() {
try {
if (cardSenderService.establishCommu()) {
System.out.println("建立通信成功!");
if (Calculatefares.totalTicketPrice == Calculatefares.coinNumber) {
System.out.println("投币金额足够");
System.out.println("Calculatefares.ticketNumber :"+Calculatefares.ticketNumber );
while (Calculatefares.ticketNumber > 0) {
if (cardSenderService.issueCardToCardreader()) {
System.out.println("出票到写卡器");
if (ticketCardReaderService.writeCard()) {
System.out.println("写卡成功");
if (cardSenderService.issueCardToOutlet()) {
//出卡到客户成功
System.out.println("出票到客户");
TvmFrame.getInstance().remove(Ticketing.getInstance());
TvmFrame.getInstance().add(TicketSuccess.getInstance());
TvmFrame.getInstance().repaint();
Thread.sleep(1000);
TvmFrame.getInstance().remove(TicketSuccess.getInstance());
TvmFrame.getInstance().add(Map.getInstance());
TvmFrame.getInstance().add(TicketPanel.getInstance());
TvmFrame.getInstance().add(StationPanel.getInstance());
TvmFrame.getInstance().add(LinePanel.getInstance());
// ThreadPool.getInstance().getThreadPool().execute(TicketNumberHandler.calculatefares); // 购票线程,当客户选择站点后开启
} else {
//出卡到客户失败
TvmFrame.getInstance().remove(Ticketing.getInstance());
TvmFrame.getInstance().add(Error.getInstance());
TvmFrame.getInstance().repaint();
cardSenderService.callBackCard();
Thread.sleep(1000);
return false; }
} else {
// 写卡失败
TvmFrame.getInstance().remove(Ticketing.getInstance());
TvmFrame.getInstance().add(Error.getInstance());
TvmFrame.getInstance().repaint();
return false;
}
} else {
// 出票到读卡器失败
TvmFrame.getInstance().remove(Ticketing.getInstance());
TvmFrame.getInstance().add(Error.getInstance());
TvmFrame.getInstance().repaint();
return false;
}
Calculatefares.ticketNumber--;
Thread.sleep(300);
}
}
} else {
// 通信故障
TvmFrame.getInstance().remove(Ticketing.getInstance());
TvmFrame.getInstance().add(Error.getInstance());
Error.getInstance().updateUI();
TvmFrame.getInstance().repaint();
return false;
}
} catch (Exception e) {
//售票的过程中抛出了异常
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
e.printStackTrace();
System.out.println("售票出现异常,请检查硬币机,读卡器,写卡器是否正常工作!");
TvmFrame.getInstance().remove(Ticketing.getInstance());
TvmFrame.getInstance().add(Error.getInstance());
TvmFrame.getInstance().repaint();
return false;
}
return false;
}请问为什么这些Jpanel为什么不能按照正常的逻辑跳转呢?

Note:sellTickets这个方法要操作硬件

解决方案 »

  1.   

    自己顶一下 
    上面的代码有点乱补充一下:TvmFrame.getInstance().remove(StationCashTicket.getInstance());
    TvmFrame.getInstance().remove(StationCardTicket.getInstance());
    TvmFrame.getInstance().remove(PriceCardTicket.getInstance());
    TvmFrame.getInstance().remove(PriceCashTicket.getInstance());
    TvmFrame.getInstance().add(Ticketing.getInstance());
    TvmFrame.getInstance().repaint();
    if(true)
    {
    TvmFrame.getInstance().remove(Ticketing.getInstance());
    TvmFrame.getInstance().add(TicketSuccess.getInstance());
    TvmFrame.getInstance().repaint();
    }假如是这样为什么不能实现连续2个Panel(Ticketing,TicketSuccess)的跳转呢?
      

  2.   

    太乱了。在一个容器内切换显示可以使用 CardLayout布局管理器。
      

  3.   

    不好意思 确实有点乱了下面我详细说下:假如说我有3个JPanel,分别是Panel1,Panel2,Panel3,panel4
    在Panel1上有一个button btn,btn 上被我添加了一个鼠标点击事件,这个鼠标点击事件是和一些
    硬件操作有关当我在panel1上点击btn时,就会进行一些硬件操作,这是应该跳到panel2(这个Panel上有一个进度条显示
    操作的进度),当事件处理完成后就要根据事件执行的结果跳到panel3(执行成功页面),或者跳到Panel4(执行失败页面)。但是我现在的问题是每当我在panel1上点击btn时,要么执行 成功跳到panel3要么执行失败跳到Panel4
    请问这是什么原因呢?是不是因为我当中有硬件操作的原因呢?
      

  4.   


    2楼的 CardLayout +1
    多层的切换最好用 CardLayout
    然后,你的问题实际上是没有理解 Swing 的线程。
    如果我没猜错的话,你所有的代码,都是写在同一个 actionPerformed() 里面的。
    TvmFrame.getInstance().add(Ticketing.getInstance()); //始终不能正常的跳到这个页面
    TvmFrame.getInstance().repaint();
    这两句代码说,我换了一个panel,重绘一下。EDT说,好的,repaint()事件已经排进我的队列里了(repaint()是非同步调用,它把一个repaint事件排进EDT队列里就返回,并不是立时就重绘),顺便说一句,我现在所有的时间都用在执行你这个actionPerformed方法本身,在你执行完以前,队列里所有排在你后面的事件都要等。然后,在这个方法稍后面一点的地方,你又写了一些逻辑,换了另外一个页面,
    也就是说,你换成Ticketing.getInstance()以后,还没有来得及重绘,就又换了另一个页面。解决方案: 可以把actionPerformed拆成两半,你换了Ticketing.getInstance()页面,送出一个重绘请求,然后说,后面还有一些逻辑,但是我想把它们排在重绘之后:
    // ...
    if (btn == e.getSource()) {  System.out.println("确定出票被点击了");
      TvmFrame.getInstance().remove(StationCashTicket.getInstance());
      TvmFrame.getInstance().remove(StationCardTicket.getInstance());
      TvmFrame.getInstance().remove(PriceCardTicket.getInstance());
      TvmFrame.getInstance().remove(PriceCashTicket.getInstance());
      TvmFrame.getInstance().add(Ticketing.getInstance()); //始终不能正常的跳到这个页面
      TvmFrame.getInstance().repaint();
      
      SwingUtilities.invokeLater(new Runnable() {
      
        @Override
        public void run() {
        
          if (sellingOneWayTicket.sellTickets()) {
            System.out.println("开始压币");
            coinModulServiceImpl.startManage();
            coinModulServiceImpl.stopManage();
          } else {
            // 当机器出现故障出票失败时将硬币全部退出
            coinModulServiceImpl.changeCoin(coinModulServiceImpl.get1NoOfCoin(),0);
            coinModulServiceImpl.outCoin();//很多时候都如果出现问题的话都是直接跳到这个页面,上面红色字体的那个页面直接过了
          }
        }
      });
    }
    // ...
      

  5.   

    非常感谢楼主的回复,最近这几天太忙了,一直没时间上csdn.是的
    所有的代码都在同一个actionperformed里面。看了你讲的感觉很清晰,我在家里的电脑的上试了下但是好像还是无法跳转样。明天到了公司了加上那些硬件再测试下,非常感谢了。
      

  6.   


    不谢,除了6楼的更改之外,这一句:TvmFrame.getInstance().repaint();
    前面加一句:TvmFrame.getInstance().invalidate();
    TvmFrame.getInstance().repaint();
    当一个容器布局内的子控件发生变化的时候,比如删掉了一些子控件,又添加了一些子控件,这时调用 invalidate(),告诉Swing的repaint机制:这个容器内的内容改变了,在下一次重绘之前需要重新计算布局(就是为它里面的子控件重新计算大小和位置,会触发其注册的LayoutManager的layoutContainer方法)。
      

  7.   

    TvmFrame.getInstance().invalidate();写错了,应该是TvmFrame.getInstance().getContentPane().invalidate();