如何在具有默认参数的插槽上使用Qt5 connect()

时间:2016-06-05 06:18:50

标签: visual-studio c++11 qt5 signals-slots

我有一些看起来像这样的代码:

public class PlayerActivity extends Activity 
    implements SurfaceHolder.Callback {

    Uri targetUri;

    MediaPlayer mediaPlayer;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean pausing = false;
    boolean isFirstTime = true;
    private SeekBar progressBar;
    private FontAwesome fullScreen;
    private FontAwesome btnPayPause;
    private TextView timeForMediaPlayer;
    Timer mTimer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.playerlayout);

        initialize();

        targetUri = Uri.parse("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");

        getWindow().setFormat(PixelFormat.UNKNOWN);
        surfaceView = (SurfaceView)findViewById(R.id.surfaceview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setFixedSize(176, 144);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setScreenOnWhilePlaying(true);

        btnPayPause.setOnClickListener(new Button.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                if (pausing) {
                    pausing = false;
                    mediaPlayer.start();
                } else {
                    if (isFirstTime) {
                        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                        mediaPlayer.setDisplay(surfaceHolder);

                        try {
                            mediaPlayer.setDataSource(getApplicationContext(), targetUri);
                            mediaPlayer.prepare();
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();
                        } catch (IllegalStateException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        mediaPlayer.start();
                        isFirstTime = false;
                    } else {
                        pausing = true;
                        mediaPlayer.pause();
                    }
                }
            }
        });

        mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
                progressBar.setSecondaryProgress(percent);
            }
        });

        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                new Thread(runnable).start();
            }
        });

        progressBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (mediaPlayer != null && fromUser) {
                    int timeToSet = (mediaPlayer.getDuration() * progress) / 100;
                    mediaPlayer.seekTo(timeToSet);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });

        fullScreen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

    }


    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {}
                int currentTime = mediaPlayer.getCurrentPosition();
                int percent = ( 100 * currentTime)  / mediaPlayer.getDuration();
                progressBar.setProgress(percent);
                final String timeToShow = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(currentTime),
                        TimeUnit.MILLISECONDS.toMinutes(currentTime) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(currentTime)),
                        TimeUnit.MILLISECONDS.toSeconds(currentTime) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(currentTime)));
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        timeForMediaPlayer.setText(timeToShow);
                    }
                });
            }
        }
    };

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        mediaPlayer.release();
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        // TODO Auto-generated method stub

    }

    private void initialize() {
        timeForMediaPlayer = (TextView) findViewById(R.id.timeForMediaPlayer);
        progressBar = (SeekBar) findViewById(R.id.progressBar);
        fullScreen = (FontAwesome) findViewById(R.id.fullScreen);
        btnPayPause = (FontAwesome) findViewById(R.id.btnPayPause);
    }
}

这很好但我想利用Qt5's new signal/slot syntax(并删除宏)。如果我将connect()更改为:

class MyClass : public QObject
{
    Q_OBJECT

signals:
    void SetValue(float value);

public slots:
    void OnSetValue(float value, bool fromDatabase = false);
}

connect(this, SIGNAL(SetValue(float)), this, SLOT(OnSetValue(float)));

我得到(在Visual Studio 2013中):

  

错误C2338:插槽需要的参数多于信号提供的参数

我可以创建一个调用OnSetValue()的中间函数,并允许设置默认参数,但这似乎浪费了代码。什么是解决这个问题的更好方法?

1 个答案:

答案 0 :(得分:3)

link提供的sim642也表示新的连接语法"可以与c + 11 lambda表达式"一起使用。对于上面的例子,我能够使用:

connect(this, &MyClass::SetValue, [=](float value) { OnSetValue(value); });

稍微复杂但是代码少于添加中间函数,并且仍然提供编译时检查。

Igor Tandetnik提供了更好的版本:

connect(this, &MyClass::SetValue, [this](float value){ OnSetValue(value); });

使用[this]替换[=](使lambda能够按值捕获范围内的所有自动变量),减少lambda的范围和出错的可能性。

相关问题