سؤال

لقد قمت بتنفيذ مستمع الماوس بسيط حيث يتغير لون الخلفية كلما دخل الماوس إلى المكون (JPanel)، ويعود مرة أخرى كلما أوراق الماوس. هذا لديه بعض المشاكل:

  • في بعض الأحيان يتحرك الماوس سريع جدا mouseexit. لم يتم إطلاق الحدث
  • إذا كان مكوني لديه أطفال، عندما يتحرك الماوس إلى الطفل الذي يثير mouseexit.
  • إذا قمت بنقل الماوس إلى الطفل بسرعة، mouseenter. لم يتم إطلاق الحدث

أنا أظن أن هذا أمر سهل للمحاربين القدامى. أي اقتراحات حول كيفية إصلاح هذا؟ أحب عدم استخدام أجهزة ضبط الوقت ومثل هذه ...

هل كانت مفيدة؟

المحلول

إذا قمت بنقل الماوس إلى الطفل بسرعة، فلن يتم تشغيل حدث Mouseenter

لم أر أبدا أن يحدث هذا، ولكن إذا كانت مشكلة، فيمكنك التعامل مع mousemoved بدلا من ذلك لإعادة تعيين الخلفية.

إذا كان مكوني لديه تشايلدز، عندما يتحرك الماوس إلى الطفل الذي يقوم بتشغيل MouseExIT

استخدم الاختبار التالي وسيتم تنفيذ التعليمات البرمجية فقط عند مغادرة حدود المكونات:

public void mouseExited(MouseEvent e) 
{
    if (! getVisibleRect().contains(e.getPoint()) )
    {
        setBackground(...);
    }
}

نصائح أخرى

هناك عدد من الحلول:

  • إضافة مستمع الماوس إلى مكونات الطفل. أيضا مستمعي حاوية، لإضافة وإزالة المستمعين مع إضافة مكونات وإزالتها. لسوء الحظ، مضيفا مستمعي الماوس اضطراب في مواقف أحداث الماوس (التصميم البشعة).
  • أضف جزءا زجاجيا فوق القمة. هذه قوية قبيحة، وإعادة توجيه الأحداث دائما تسبب مشاكل.
  • إضافة AWTEventListener إلى الافتراضي Toolkit والتصفية من خلال الأحداث التي تهتم بها. هذا لسوء الحظ يتطلب إذن أمان.
  • دفع مخصص EventQueue وتصفية الأحداث. يتطلب هذا إذن أمني، وتطبيق تطبيقات PLEST و WebStart / JNLP الحصول على هذا الإذن على أي حال.

بعد تجربة طرق مختلفة على حاوية، دون نجاح، انتهى بي الأمر باستخدام الموقت. وبعد لم يساعد ذلك على أن حاوية بلدي تحتوي على عناصر تحتاج بالفعل إلى مستمعي الماوس عليها.

نهج الموقت يعني أيضا أنه يمكنني تأخير التغيير لفترة قصيرة. (في حالتي، أظهر أزرار إضافية في عقدة شجرة (حاوية)، وكذلك تغيير الخلفية.)

على mouseentered () على الحاوية، الموقت يتم إنشاؤه (إن لم يكن هناك بالفعل) الذي يكرر كل 260 مللي ثانية. في كل مكالمة من المؤقت، يحدد ما إذا كان الماوس داخل الحاوية. إذا كان الأمر كذلك، في المرة الأولى تشير إلى الماوس فوق. إذا لم يكن الأمر كذلك، فإنه يشير إلى عدم وجود الماوس وتوقف الموقت.

في Scala، هذا كما يلي، حيث تتطلب الطريقة EntryExit () ترميز ما إذا كان الماوس قد انتهى أم لا (حيث لا تؤثر مكالمات متعددة بنفس القيمة):

abstract class MouseInterpreter(component: JComponent) extends MouseAdapter {
  ...
  private var mouseOverAction: () => Unit   = () => {}
  private var mouseOverTimer: Option[Timer] = None
  ...
  def entryExit(entered: Boolean) // this is an abstract method

  override def mouseEntered(e: MouseEvent) {
    if (mouseOverTimer.isEmpty) {
      val aTimer = new Timer(260, new ActionListener {
        def actionPerformed(e: ActionEvent) {
          mouseOverAction()
        }
      })
      mouseOverTimer = Some(aTimer)
      mouseOverAction = () => {
        mouseOverAction = () => {
          val point = MouseInfo.getPointerInfo.getLocation
          SwingUtilities.convertPointFromScreen(point, component)
          if (component.getVisibleRect.contains(point))
            entryExit(entered = true)
          else {
            entryExit(entered = false)
            aTimer.stop()
            mouseOverTimer = None
            mouseOverAction = () => {}
          }
        }
      }
      aTimer.setRepeats(true)
      aTimer.start()
    }
  }
...
}

لا أستطيع إعادة إنتاج هذا السلوك. يرجى تعديل سؤالك لتوفير نموذج رمز قصير يدل على المشكلة.

عندما أقوم بإنشاء JPanel، ووضع شيء فيه، لا يحصل JPanel على MouseExIT عندما يتحرك الماوس فوق مكون الطفل من JPanel. أنا أظن أنك أضفت مواد مواليد الأطفال إلى الأطفال.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top