Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTimeEdit opens with the selected section being hours
Qt 6.11 is out! See what's new in the release blog

QTimeEdit opens with the selected section being hours

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 3 Posters 936 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • PerdrixP Offline
    PerdrixP Offline
    Perdrix
    wrote on last edited by
    #1

    I have a table item editor delegate set to edit an exposure time field.
    The QTimeEdit display format is set to "hh:mm:ss".

    The code to insert the model data reads:

    int secs{ index.model()->data(index, Qt::EditRole).toInt() };
    if (secs > 66399) secs = 86399;		// 24 hours less 1 ms
    timeEdit = qobject_cast<QTimeEdit*>(editor);
    Q_ASSERT(timeEdit);
    QTime time{ QTime(0, 0) };
    time = time.addSecs(secs);
    timeEdit->setTime(time);
    timeEdit->setCurrentSection(QDateTimeEdit::MinuteSection);
    

    which I thought should select the minutes when the editor opened, but I see:

    fd2f64bf-52bd-4dfe-839f-da9b7b052a2e-image.png

    How to get it to select the minutes section?

    Thanks
    David

    JonBJ 1 Reply Last reply
    0
    • PerdrixP Offline
      PerdrixP Offline
      Perdrix
      wrote on last edited by Perdrix
      #11

      This worked:

      In ItemEditDelegate::createEditor():

      {
      	QTimeEdit* editor = new QTimeEdit(parent);
      	editor->setDisplayFormat("hh:mm:ss.zzz");
      	//
      	// Commented out as parent class already sets an eventFilter up!
      	//
      	// editor->installEventFilter(const_cast<ItemEditDelegate*>(this));
      
      	return editor;
      }
      

      and this is the event filter:

      	bool ItemEditDelegate::eventFilter(QObject* watched, QEvent* event)
      	{
      		if (QEvent::Show == event->type())
      		{
      			QTimeEdit* timeEdit{ dynamic_cast<QTimeEdit*>(watched) };
      			QShowEvent* showEvent{ static_cast<QShowEvent*>(event) };
      			if (timeEdit)
      				if (!showEvent->spontaneous())
      			{
      				QTimer::singleShot(100,
      					[timeEdit]()
      				{
      					timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
      				});
      			}
      		}
      		//
      		// Always call the base class event filter (even though it currently 
      		// only handles stuff for TextEdit controls)
      		//
      		return Inherited::eventFilter(watched, event);
      	}
      
      1 Reply Last reply
      1
      • PerdrixP Perdrix

        I have a table item editor delegate set to edit an exposure time field.
        The QTimeEdit display format is set to "hh:mm:ss".

        The code to insert the model data reads:

        int secs{ index.model()->data(index, Qt::EditRole).toInt() };
        if (secs > 66399) secs = 86399;		// 24 hours less 1 ms
        timeEdit = qobject_cast<QTimeEdit*>(editor);
        Q_ASSERT(timeEdit);
        QTime time{ QTime(0, 0) };
        time = time.addSecs(secs);
        timeEdit->setTime(time);
        timeEdit->setCurrentSection(QDateTimeEdit::MinuteSection);
        

        which I thought should select the minutes when the editor opened, but I see:

        fd2f64bf-52bd-4dfe-839f-da9b7b052a2e-image.png

        How to get it to select the minutes section?

        Thanks
        David

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #2

        @Perdrix said in QTimeEdit opens with the selected section being hours:

        timeEdit->setCurrentSection(QDateTimeEdit::MinuteSection);

        I think you need to do void QDateTimeEdit::setSelectedSection(QDateTimeEdit::Section section) for selection.

        1 Reply Last reply
        1
        • PerdrixP Offline
          PerdrixP Offline
          Perdrix
          wrote on last edited by
          #3

          A good point (what's setCurrentSection actually do then?)...

          I added setSelectedSection:

          timeEdit->setTime(time);
          timeEdit->setCurrentSection(QDateTimeEdit::MinuteSection);
          timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
          

          but it made no difference :(

          D.

          jsulmJ JonBJ 2 Replies Last reply
          0
          • PerdrixP Perdrix

            A good point (what's setCurrentSection actually do then?)...

            I added setSelectedSection:

            timeEdit->setTime(time);
            timeEdit->setCurrentSection(QDateTimeEdit::MinuteSection);
            timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
            

            but it made no difference :(

            D.

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #4

            @Perdrix said in QTimeEdit opens with the selected section being hours:

            but it made no difference :(

            Of course not: you used QDateTimeEdit::MinuteSection for both calls.
            Use only setCurrentSection and then only setSelectedSection to see the difference. I think setCurrentSection will not select anything, only move the cursor to the section. setSelectedSection moves the cursor and selects the section (as described in the documentation).

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            JonBJ 1 Reply Last reply
            0
            • jsulmJ jsulm

              @Perdrix said in QTimeEdit opens with the selected section being hours:

              but it made no difference :(

              Of course not: you used QDateTimeEdit::MinuteSection for both calls.
              Use only setCurrentSection and then only setSelectedSection to see the difference. I think setCurrentSection will not select anything, only move the cursor to the section. setSelectedSection moves the cursor and selects the section (as described in the documentation).

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #5

              @jsulm said in QTimeEdit opens with the selected section being hours:

              Of course not: you used QDateTimeEdit::MinuteSection for both calls.

              Umm, but that is what the OP is asking to do! The screenshot shows the hours is selected, OP wants the munutes (middle section) to be selected, but claims setCurrentSection(QDateTimeEdit::MinuteSection) is not achieving that?

              jsulmJ 1 Reply Last reply
              0
              • JonBJ JonB

                @jsulm said in QTimeEdit opens with the selected section being hours:

                Of course not: you used QDateTimeEdit::MinuteSection for both calls.

                Umm, but that is what the OP is asking to do! The screenshot shows the hours is selected, OP wants the munutes (middle section) to be selected, but claims setCurrentSection(QDateTimeEdit::MinuteSection) is not achieving that?

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #6

                @JonB My answer was related to: "what's setCurrentSection actually do then?" + "I added setSelectedSection" + "but it made no difference".

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                JonBJ 1 Reply Last reply
                0
                • jsulmJ jsulm

                  @JonB My answer was related to: "what's setCurrentSection actually do then?" + "I added setSelectedSection" + "but it made no difference".

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #7

                  @jsulm
                  :) I am testing how it behaves for me.....

                  1 Reply Last reply
                  0
                  • PerdrixP Perdrix

                    A good point (what's setCurrentSection actually do then?)...

                    I added setSelectedSection:

                    timeEdit->setTime(time);
                    timeEdit->setCurrentSection(QDateTimeEdit::MinuteSection);
                    timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
                    

                    but it made no difference :(

                    D.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #8

                    @Perdrix
                    OK, here is the deal :) I agree your code does not work for me. It appears that when the time edit is shown something in Qt code initialises the selection to the first section unconditionally, hence the timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection) does not take as you would expect.

                    I discovered this by guessing and putting in a delayed timer to set the selection:

                        QTimer::singleShot(1000, [timeEdit]() { qDebug() << "Hello"; timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection); });
                    

                    I put this in after creating the QTimeEdit. It works, and you can see the selection move from the hours when it is initially shown to the minutes when the timer fires. Note that the time delay size seems to be critical here. I tried with 0 and even with 100 and it did not work. For me, I needed 1000 (1 second) before it worked! You will need to play with that figure depending on your machine and where you call it/show the widget. Clearly something is going on in Qt after the widget is shown.

                    If you want to get it "better" you probably want to subclass QTimeEdit so as to override the showEvent(), so that you are "closer" to the time it will be shown. Or, maybe you can do it in the show event of its parent widget or window or something. My 1 second was on a standalone program which had to start up and show its top-level widget containing the QTimeEdit, you may find faster if your Qt program is already running.

                    UPDATE
                    If you are prepared to subclass the QTimeEdit so that you can override showEvent I got better "performance". Still needed to use a time delay, but getting that down to 100 makes it so the user does not see the selection start at hours and then move:

                    class MyTimeEdit : public QTimeEdit
                    {
                    public:
                        explicit MyTimeEdit(QWidget *parent = nullptr) : QTimeEdit(parent)
                        {
                        }
                        explicit MyTimeEdit(const QTime &time, QWidget *parent = nullptr) : QTimeEdit(time, parent)
                        {
                        }
                        void showEvent(QShowEvent *event) override
                        {
                            QTimeEdit::showEvent(event);
                            // next line commented out because still does not work
                    //        this->setSelectedSection(QDateTimeEdit::MinuteSection);
                            // next line still requires `100` delay on my machine, but better than `1000`
                            QTimer::singleShot(100, [this]() { qDebug() << "Hello"; this->setSelectedSection(QDateTimeEdit::MinuteSection); });
                        }
                    };
                    

                    I have written up my findings for posterity at https://stackoverflow.com/a/73879701/489865 :)

                    1 Reply Last reply
                    0
                    • PerdrixP Offline
                      PerdrixP Offline
                      Perdrix
                      wrote on last edited by
                      #9

                      Well I tried this:

                      	void ItemEditDelegate::setEditorData(QWidget* editor,
                      		const QModelIndex& index) const
                      	{
                      		QComboBox* combo{ nullptr };
                      		QTimeEdit* timeEdit{ nullptr };
                      
                      		switch (static_cast<Column>(index.column()))
                      		{
                                      : STUFF DELETED
                      		case Column::Exposure:
                      			{
                      				double secs{ index.model()->data(index, Qt::EditRole).toDouble() };
                      				if (secs > 66399.999) secs = 86399.999;		// 24 hours less 1 ms
                      				double msecs = secs * 1000.0;
                      				timeEdit = qobject_cast<QTimeEdit*>(editor);
                      				Q_ASSERT(timeEdit);
                      				QTime time{ QTime(0, 0) };
                      				time = time.addMSecs(msecs);
                      				timeEdit->setTime(time);
                      				//
                      				// timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
                      				// didn't work, so set a singleshot timer to do it after 100 ms
                      				//
                      				QTimer::singleShot(100,
                      					[timeEdit]() 
                      						{ 
                      							qDebug() << "Hello";
                      							timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
                      						});
                      			}
                      			break;
                      		default:
                      			Inherited::setEditorData(editor, index);
                      		}
                      	}
                      

                      which appeared to work except that when I closed the TimeEdit control by clicking outside it, I got:

                      f55f9675-3cd9-4060-a204-5b585d2630fc-image.png

                      b25fef27-7b8a-4386-baba-172092c1a227-image.png

                      :(

                      David

                      JonBJ 1 Reply Last reply
                      0
                      • PerdrixP Perdrix

                        Well I tried this:

                        	void ItemEditDelegate::setEditorData(QWidget* editor,
                        		const QModelIndex& index) const
                        	{
                        		QComboBox* combo{ nullptr };
                        		QTimeEdit* timeEdit{ nullptr };
                        
                        		switch (static_cast<Column>(index.column()))
                        		{
                                        : STUFF DELETED
                        		case Column::Exposure:
                        			{
                        				double secs{ index.model()->data(index, Qt::EditRole).toDouble() };
                        				if (secs > 66399.999) secs = 86399.999;		// 24 hours less 1 ms
                        				double msecs = secs * 1000.0;
                        				timeEdit = qobject_cast<QTimeEdit*>(editor);
                        				Q_ASSERT(timeEdit);
                        				QTime time{ QTime(0, 0) };
                        				time = time.addMSecs(msecs);
                        				timeEdit->setTime(time);
                        				//
                        				// timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
                        				// didn't work, so set a singleshot timer to do it after 100 ms
                        				//
                        				QTimer::singleShot(100,
                        					[timeEdit]() 
                        						{ 
                        							qDebug() << "Hello";
                        							timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
                        						});
                        			}
                        			break;
                        		default:
                        			Inherited::setEditorData(editor, index);
                        		}
                        	}
                        

                        which appeared to work except that when I closed the TimeEdit control by clicking outside it, I got:

                        f55f9675-3cd9-4060-a204-5b585d2630fc-image.png

                        b25fef27-7b8a-4386-baba-172092c1a227-image.png

                        :(

                        David

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #10

                        @Perdrix
                        Dunno, works in a standalone, something to do with your usage/context. My guess is that your QTimeEdit widget is the edit widget and that comes and goes and is not valid after this setEditorData() when the timer expires? In some shape or form. You could attach a slot to editor->destroyed() to debug when it gets destroyed?

                        Other than that, start by removing the timeEdit argument to the lambda and verify the qDebug() << "Hello"; all works.

                        which appeared to work except that when I closed the TimeEdit control by clicking outside it, I got:

                        Ah, so initially (if you don't click to destroy) it worked OK? Only later when closing you had a problem? The editor widget has been destroyed and then the single shot expires? (Like you click away within 100msecs?)

                        UPDATE

                        • Why do you not call the base implementation of setEditorData() in your exposure case? Does that make any difference?
                        • I don't know, maybe the single shot would be better placed in QStyledItemDelegate::createEditor()? (Probably not, but looking for clues...)

                        Another thought: if it's an issue of the editor widget getting destroyed. instead of using the static QTimer::singleShot() create a QTimer instance, set its parent to the timeEdit and set it as single shot. That way I'm hoping that it will automatically disconnect the slot accessing the QTimeEdit timeEdit if it gets destroyed?

                        1 Reply Last reply
                        0
                        • PerdrixP Offline
                          PerdrixP Offline
                          Perdrix
                          wrote on last edited by Perdrix
                          #11

                          This worked:

                          In ItemEditDelegate::createEditor():

                          {
                          	QTimeEdit* editor = new QTimeEdit(parent);
                          	editor->setDisplayFormat("hh:mm:ss.zzz");
                          	//
                          	// Commented out as parent class already sets an eventFilter up!
                          	//
                          	// editor->installEventFilter(const_cast<ItemEditDelegate*>(this));
                          
                          	return editor;
                          }
                          

                          and this is the event filter:

                          	bool ItemEditDelegate::eventFilter(QObject* watched, QEvent* event)
                          	{
                          		if (QEvent::Show == event->type())
                          		{
                          			QTimeEdit* timeEdit{ dynamic_cast<QTimeEdit*>(watched) };
                          			QShowEvent* showEvent{ static_cast<QShowEvent*>(event) };
                          			if (timeEdit)
                          				if (!showEvent->spontaneous())
                          			{
                          				QTimer::singleShot(100,
                          					[timeEdit]()
                          				{
                          					timeEdit->setSelectedSection(QDateTimeEdit::MinuteSection);
                          				});
                          			}
                          		}
                          		//
                          		// Always call the base class event filter (even though it currently 
                          		// only handles stuff for TextEdit controls)
                          		//
                          		return Inherited::eventFilter(watched, event);
                          	}
                          
                          1 Reply Last reply
                          1

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved