جافا سوينغ: تغيير لون الخلفية على الماوس فوق
-
18-09-2019 - |
سؤال
لقد قمت بتنفيذ مستمع الماوس بسيط حيث يتغير لون الخلفية كلما دخل الماوس إلى المكون (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. أنا أظن أنك أضفت مواد مواليد الأطفال إلى الأطفال.