GVKun编程网logo

如何创建Tkinter GUI停止按钮以打破无限循环?(tkinter after怎么停止)

23

本篇文章给大家谈谈如何创建TkinterGUI停止按钮以打破无限循环?,以及tkinterafter怎么停止的知识点,同时本文还将给你拓展android–后退按钮陷入无限循环?、android–如何停

本篇文章给大家谈谈如何创建Tkinter GUI停止按钮以打破无限循环?,以及tkinter after怎么停止的知识点,同时本文还将给你拓展android – 后退按钮陷入无限循环?、android – 如何停止/启动包含创建无限循环的服务、angularjs ui-router生成无限循环、c – 如何避免线程优化器==无限循环?等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

如何创建Tkinter GUI停止按钮以打破无限循环?(tkinter after怎么停止)

如何创建Tkinter GUI停止按钮以打破无限循环?(tkinter after怎么停止)

因此,我有一个Tkinter GUI,其中有两个简单的选项,即开始和停止按钮。我已经定义了GUI布局:

from Tkinter import *def scanning():    while True:        print "hello"root = Tk()root.title("Title")root.geometry("500x500")app = Frame(root)app.grid()

此处的“开始”按钮运行无限循环扫描,而“停止”按钮在按下时应会中断:

start = Button(app, text="Start Scan",command=scanning)stop = Button(app, text="Stop",command="break")start.grid()stop.grid()

但是,当我按下“开始”按钮时,它总是被按下(假定由于无限循环)。但是,我 无法单击“停止”按钮 来打破while循环。

答案1

小编典典

您不能while True:在Tkinter事件循环所处的同一线程中启动循环。这样做将阻塞Tkinter的循环并导致程序冻结。

对于一个简单的解决方案,您可以Tk.after每秒钟左右在后台运行一个进程。下面是一个脚本来演示:

from Tkinter import *running = True  # Global flagdef scanning():    if running:  # Only do this if the Stop button has not been clicked        print "hello"    # After 1 second, call scanning again (create a recursive loop)    root.after(1000, scanning)def start():    """Enable scanning by setting the global flag to True."""    global running    running = Truedef stop():    """Stop scanning by setting the global flag to False."""    global running    running = Falseroot = Tk()root.title("Title")root.geometry("500x500")app = Frame(root)app.grid()start = Button(app, text="Start Scan", command=start)stop = Button(app, text="Stop", command=stop)start.grid()stop.grid()root.after(1000, scanning)  # After 1 second, call scanningroot.mainloop()

当然,您可能希望将此代码重构为一个类并running成为其属性。另外,如果您的程序变得很复杂,那么研究Python的threading模块将是有益的,这样您的scanning函数可以在单独的线程中执行。

android – 后退按钮陷入无限循环?

android – 后退按钮陷入无限循环?

我的应用程序目前停留在物理后退按钮的无限循环中.该程序设置为加载启动画面,然后转换到主菜单.一旦进入主菜单,用户就可以切换到他们选择的另一个活动.例如:新的游戏活动.一旦用户进入新的游戏活动,我希望他们能够点击后退按钮并将其带到主菜单.一旦回到主菜单,如果他们再次点击后退按钮,我希望它退出游戏.

这就是我为每个活动使用的内容:

public boolean onKeyDown(int keyCode,KeyEvent event) {

    if ((keyCode == KeyEvent.KEYCODE_BACK)) { 
        startActivity(new Intent(NewGameActivity.this,MenuActivity.class));
    }
    return super.onKeyDown(keyCode,event); 
}

它工作正常,并使用户回到主菜单没有问题.但是如果用户在主菜单上再次点击后退按钮,它将把他们带到他们刚从中逃出的屏幕.所以它每次都会循环回到上一个屏幕.

这是主菜单的设置方式:

public boolean onKeyDown(int keyCode,KeyEvent event) {

    if ((keyCode == KeyEvent.KEYCODE_BACK)) { 
        stopService(new Intent(MenuActivity.this,BGMusicService.class));
        MenuActivity.this.finish();
    }
    return super.onKeyDown(keyCode,event); 
}

如果我在第一次加载主菜单时按下后退按钮它将正常工作并关闭游戏.如果我之前点击后退按钮从一个屏幕进入主菜单,它只会混乱.

更新:

好的,那种工作.当我点击主屏幕上的后退按钮时,音乐停止,它就像试图关闭应用程序一样,但它会再次闪回主屏幕.我每次都要打两次.

解决方法

@H_301_30@ 您应该在活动的onKeyDown方法中调用 finish(),以便实际从堆栈中删除当前活动.

这样的事情应该有效:

public boolean onKeyDown(int keyCode,KeyEvent event)
{
  if (keyCode == KeyEvent.KEYCODE_BACK)
  { 
    startActivity(new Intent(NewGameActivity.this,MenuActivity.class));
    finish();
  }

  return super.onKeyDown(keyCode,event); 
}

android – 如何停止/启动包含创建无限循环的服务

android – 如何停止/启动包含创建无限循环的服务

因此,对于后台,我正在尝试创建一个通过麦克风连续记录并将数据存储在缓冲区中的应用程序.该程序的目标是对缓冲区中的数据执行某种类型的处理并对其进行操作.
目前,应用程序只是将数据读入缓冲区并尽快写入.当运行应用程序时,人们会对着麦克风说话,然后听到你刚刚说出来的另一端.

现在,我对Android的经验不足以开始发挥作用.我正在进行读写操作,这是一个无限循环.服务如下:

public class AudioService extends Service {

private final int MIC = AudioSource.MIC;
private final int SAMPLE = 44100;
private final int CHANNELI = AudioFormat.CHANNEL_IN_MONO;
private final int CHANNELO = AudioFormat.CHANNEL_OUT_MONO;
private final int FORMAT = AudioFormat.ENCODING_PCM_16BIT;
private final int BUFFERSIZE = AudioRecord.getMinBufferSize(SAMPLE,CHANNELI,FORMAT);
private final int STREAM = AudioManager.STREAM_MUSIC;
private final int MODE = AudioTrack.MODE_STREAM;
private boolean play = true;

AudioRecord recorder = null;
AudioTrack track = null;

short[] buffer = null;

public void OnCreate() {

}

@Override
public int onStartCommand(Intent intent,int flags,int startId) {
    recorder = new AudioRecord(MIC,SAMPLE,FORMAT,BUFFERSIZE);
    track = new AudioTrack(STREAM,CHANNELO,BUFFERSIZE,MODE);
    buffer = new short[BUFFERSIZE];
    recorder.startRecording();
    track.play();

    while (play) {
        recorder.read(buffer,buffer.length);
        track.write(buffer,buffer.length);
    }
    return START_STICKY;
}

在活动中单击“记录”按钮时,将调用此服务.我希望能够单击记录并选择单击取消以停止此循环.实现此目的的下面的监听器是:

private OnClickListener Recording = new OnClickListener() {
    public void onClick(View v) {

        serviceIntent = new Intent(getApplicationContext(),AudioService.class);
        serviceIntent.putExtra("exTradata","somedata");
        startService(serviceIntent);

        record.setEnabled(false);
        cancel.setEnabled(true);
        cancel.requestFocus();

};

现在问题变得明显了.应用程序在到达startService(serviceIntent)时无法完成执行,只是在余额中挂起.

那么我的追索权是什么?我正在考虑从无限循环内部控制服务的一些方法,但我对Android的经验不足让我想知道如何做到这一点.通过在循环中实例化一个新按钮来煽动某种打破方式;所以在startIntent期间,我将能够突破循环并“结束疯狂”.

任何帮助,将不胜感激.我也意识到这个服务应该从UI的一个单独的线程开始,以避免“应用程序没有响应…”问题,但这是另一个主题.我现在的主要目标是打破循环,我将不胜感激任何有关如何做到这一点的帮助或方向.

最佳答案

The service is below

问题#1:你无法摆脱你的循环.

问题2:你的循环正在主应用程序线程上运行.

这是不好的.

So what’s my recourse?

您将无限循环放在后台线程中,使用某些东西(例如,AtomicBoolean)告诉该线程在需要时停止(例如,onDestroy()).

I’m also realizing this service should be started on a seperate thread from UI so as to avoid the “App is not responding…” issue but that’s sort of another topic.

不,这是同一个话题.

Inciting some way to break by maybe instantiating a new button inside the loop

服务没有UI.

由于您在该活动中有一个触发对startService()的调用的“记录”按钮,因此该活动可能有一个“停止”按钮,该按钮触发对stopService()的调用.

一旦确定调用stopService()的位置和方法,那么您需要做的就是获取服务的onDestroy()以使后台线程停止运行,因为调用stopService()将触发onDestroy().

angularjs ui-router生成无限循环

angularjs ui-router生成无限循环

我知道这个问题已被多次讨论过,但解决方案并不符合我的要求.任务很简单.如果用户未登录,则应将用户重定向到登录页面.当我在$on中执行它时,它会产生无限循环.让我知道什么是最好的解决方案.

var adminpanel = angular.module('administrator',['ngMessages','ui.router','ui.bootstrap','ngCookies']);
    adminpanel.config(function ($stateProvider,$urlRouterProvider) {
    //    $urlRouterProvider.otherwise("/login");
        $urlRouterProvider.otherwise( function($injector,$location) {
                var $state = $injector.get("$state");
                $state.go("login");
            });
                $stateProvider
                .state('login',{
                                url: "/login",controller:"userCtrl",templateUrl: "views/login.tpl.html",permissions:{except:['admin']}
                                }
                      )
                  .state('menu',{
                                templateUrl: "views/menu.tpl.html",controller:'adminCtrl',permissions:{allow : ['admin']}
                                }
                      )
                  .state('menu.dashboard',{
                                url: "/dashboard",templateUrl: "views/dashboard.tpl.html",permissions:{allow : ['admin']}
                                }
                      )

});


adminpanel.run([ '$rootScope','$state','$stateParams','$cookieStore',function ($rootScope,$state,$stateParams,$cookieStore) {
 $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
        $rootScope.$on('$stateChangeStart',function(event,toState,fromState){

            if($rootScope.session == undefined && $cookieStore.get('name') == undefined){$rootScope.session={}}
            else if($rootScope.session == undefined && $cookieStore.get('name') != undefined){
                    $rootScope.session={set:true,name : $cookieStore.get('name'),userid :$cookieStore.get('userid'),role:$cookieStore.get('role')};
            };
        //Added below lines as update    
             if(toState.name === "login"){
              return;
            }
        //Added above lines as update
        var authorized = true;
         if(Object.keys($rootScope.session).length === 0){
              event.preventDefault();
            $state.go('login');
         }
        else if(Object.keys(toState.permissions).length !=0){
                    console.log($rootScope.session.role);
                    angular.forEach(toState.permissions,function(value,key){
                     angular.forEach(value,function(role){
                        if(key === 'except' && role === $rootScope.session.role)
                        {authorized = false;}
                        else if(key === 'allow' && role !== $rootScope.session.role)
                        {authorized = false;};
                    });
                });
}
if(!authorized){
                        event.preventDefault();
                        $state.go('menu.dashboard');
                };

        });

}]);

在此先感谢您的帮助.

更新1:

解决方案很好.但是,如果用户已登录,则用户在尝试通过地址栏查看时不应访问登录页面.所以我用except键创建了一个权限参数.

但是如果用户通过地址栏点击登录页面,则会生成登录页面,不应该将登录页面重定向到menu.dashboard.

希望我很清楚.

解决方法

这里的重点是避免重定向,如果已经发生,如果已经重定向:

...
// never redirect to state,if already going there
if(toState.name === "login"){
  return;
}

// evaluate some IF here only if we go to other state then login
if(Object.keys($rootScope.session).length === 0) {
  event.preventDefault();
  $state.go('login');
  return;

}

c – 如何避免线程优化器==无限循环?

c – 如何避免线程优化器==无限循环?

在今天的 code review中,我偶然发现了以下一些代码(稍微修改后发布):

while (!initialized)
{
  // The thread can start before the constructor has finished initializing the object.
  // Can lead to strange behavior. 
  continue;
}

这是在新线程中运行的前几行代码.在另一个线程中,一旦初始化完成,它将initialized设置为true.

我知道优化器可以将其变成无限循环,但是避免这种情况的最佳方法是什么?

>挥发性 – considered harmful
>调用isInitialized()函数而不是直接使用变量 – 这会保证内存屏障吗?如果函数是内联声明的,该怎么办?

还有其他选择吗?

编辑:

应该早点提到这个,但这是需要在Windows,Linux,Solaris等上运行的可移植代码.我们主要使用Boost.Thread作为我们的便携式线程库.

解决方法

调用一个函数根本没有用;即使一个函数没有内联声明,它的主体仍然可以内联(除非是极端的东西,比如将你的isInitialized()函数放在另一个库中并动态链接它).

想到两个选项:

>声明初始化为原子标志(在C 0x中,您可以使用std :: atomic_flag;否则,您将需要查阅线程库的文档以了解如何执行此操作)>使用信号量;在另一个线程中获取它并在此线程中等待它.

关于如何创建Tkinter GUI停止按钮以打破无限循环?tkinter after怎么停止的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于android – 后退按钮陷入无限循环?、android – 如何停止/启动包含创建无限循环的服务、angularjs ui-router生成无限循环、c – 如何避免线程优化器==无限循环?等相关知识的信息别忘了在本站进行查找喔。

本文标签: