JList实现随意切换歌曲、更新线程以及问题分析

   如果在JList中添加一个ListSelectionListener,在监听到动作之后进行播放音乐。如果在播放过程中进行歌曲切换,那么先前进行播放的进程无法关闭,会造成多个播放进程同时运行。

   如何解决这个问题呢? 解决方法如下(实现上一曲、下一曲、暂停和播放,三个按钮以及JList点击元素播放音乐):  

public String listener(JButton b1, JButton b2, JButton b3) {


		list.addListSelectionListener(new ListSelectionListener() {


			@Override
			public void valueChanged(ListSelectionEvent e) {
				// TODO Auto-generated method stub
				flag = flag + 1; // 俩次点击解决


				if ((flag % 2) == 0) { // 监听到俩次
					str = (String) list.getSelectedValue();
					/** 调用播放音乐的类并传入播放音乐名称 **/
					playMusic p = new playMusic(str);
					try {
						p.getConnection();
					} catch (NoPlayerException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					p.start();


					// System.out.println("播放: "+str);


					/** 播放按钮监听部分 **/
					/* 上一曲 */
					ActionListener b1Action = new ActionListener() {


						@Override
						public void actionPerformed(ActionEvent arg0) {
							// TODO Auto-generated method stub
							p.close();
							System.out.println("ok");
							for (int i = 0; i < songs.length; i++) {
								if (songs[i].equals(str)) {


									str = songs[i - 1];
									playMusic p = new playMusic(str);
									try {
										p.getConnection();
										System.out.println("正在播放:" + str);
									} catch (NoPlayerException e1) {
										// TODO Auto-generated catch block
										e1.printStackTrace();
									} catch (IOException e1) {
										// TODO Auto-generated catch block
										e1.printStackTrace();
									}
									p.start();
									break;
								}
							}
						}


					};
					b1.addActionListener(b1Action);


					/* 暂停播放 */
					ActionListener b2Action = new ActionListener() {


						@Override
						public void actionPerformed(ActionEvent e) {
							// TODO Auto-generated method stub
							if (!Booleanflag) {
								p.stop();
								Booleanflag = true;
								System.out.println("stop");
							} else {
								p.start();
								Booleanflag = false;
								System.out.println("start");
							}
						}


					};
					b2.addActionListener(b2Action);


					/* 下一曲 */
					ActionListener b3Action = new ActionListener() {


						@Override
						public void actionPerformed(ActionEvent e) {
							// TODO Auto-generated method stub
							p.close();
							System.out.println("ok");
							for (int i = 0; i < songs.length; i++) {
								if (songs[i].equals(str)) {
									str = songs[i + 1];
									playMusic p = new playMusic(str);
									try {
										p.getConnection();
										System.out.println("正在播放:" + str);
									} catch (NoPlayerException e1) {
										// TODO Auto-generated catch block
										e1.printStackTrace();
									} catch (IOException e1) {
										// TODO Auto-generated catch block
										e1.printStackTrace();
									}
									p.start();
									break;
								}
							}
						}
					};
					b3.addActionListener(b3Action);


					/** 衔接下一次点击,切换歌曲部分 **/
					list.addListSelectionListener(new ListSelectionListener() {


						@Override
						public void valueChanged(ListSelectionEvent e) {
							// TODO Auto-generated method stub
							if ((flag % 2) == 0) { // 尽量减少重复的操作
								p.close();
								b2.removeActionListener(b2Action);// 点击列表进行切换歌曲的时候一处监听器
								b1.removeActionListener(b1Action);
								b3.removeActionListener(b3Action);
								System.out.println(flag);
								list.removeListSelectionListener(this);
							}
						}
					});
				}
			}
		});
		return str;


	}

     解决方法的原理是:对一个事件构造多个监听器。(俩个,内嵌入一个JList监听器)

     监听流程:第一次点击List对象,运行播放;第二次,点击List对象,执行第一次监听器中的内嵌监听对象的内容,因为在同一个代码块中(监听器),线程对象未变,此时关闭上次播放的播放线程对象。同时又会出现一个新的内嵌监听对象(俩个监听器),但是前面的内嵌监听器(俩个监听器的第二个监听器)并不会消失,因此p.close()操作会被执行俩次,而后每点击一次JList对象增加一个内嵌监听器,p.close()多执行一次,不断叠加。但是,前面的第二个监听器中的p线程是消亡的,故此有效的p.close()只有执行一次,为最新生成的内嵌监听器里面的p.close()。

    解决办法:在内嵌监听器(俩个监听器的第二个监听器)中加入代码:list.removeListSelectionListener(this);  消除当前的匿名内部监听器。

     

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长臂人猿

客官们众筹请博主喝杯奶茶吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值