طراحی اپلیکیشن دسکتاپ با Javafx

سلام، تو این پست قصد دارم یک روال کلی از پروژه ساده دسکتاپ با javafx رو بهتون نشون بدم. برای اینکار میخوام یک Music player اولیه رو با این ابزار پیاده سازی کنم. خواهید دید که اصلا چیز سختی نیست و علاوه جذابیت خاص خودش به راحتی قابل انجام است.من از ابزار های زیر استفاده میکنم:JDK 8IntelliJ IDEA CommunityScene builderدو مورد اولی رو احتمال زیاد باهاشون آشنایی دارید، Scene builder ابزاری هست که به شما کمک میکنه جلوه بصری نرم افزار خودتون رو راحت تر پیاده سازی کنید. خروجی کد fxml میده که بعدا میتونید اون رو تو پروژه جاوا بارگیری کنید. 1. ساخت پروژه اولیهدر intellij از قسمت new project مستقیم javafx رو انتخاب کنید. برای شما پروژه ساده ای ایجاد میشود که در پکیج sample شامل controller.java , main.java, sample.fxml می باشد. میتونید به دلخواه خودتون ساختار پکیج بندی پروژه رو تغییر بدید که فعلا من اینجا برای سادگی از اینکار صرف نظر میکنم. 2. طراحی viewوارد محیط scene builder میشویم میتوانید اونو مستقیم روی سیستمتون نصب کنید یا اینکه از طریق intellij باهاش کار کنید. ترجیح من اینه که از روش اول استفاده کنم(امکانات بیشتری بهتون میده). Scene builderبه راحتی میتونید کامپوننت های مورد نیاز خودتون رو به صورت کشیدن و رها کردن به صفحه بندیتون اضافه کنید من برای کار خودم از موجودیت های زیر استفاده میکنم: AnchorPaneیکی از نگه دارنده ها در javafx هست که به شما کمک میکنه صفحه بندی مورد نظرتون رو بسازید. با استفاده از نگه دارنده ها میتونید کامپوننت ها (نظیر دکمه، تکست فیلد و نوار) رو به شکل خاصی نمایش بدید.2. ToolBarیک منوی خیلی ساده در اختیارتون قرار میده که در ابتدا فقط شامل یک دکمه هست از اون برای انتخاب موسیقی دلخواه استفاده میکنیم3. Sliderبرای نمایش وضعیت پخش موسیقی مورد نظر استفاده میکنیم(اینکه درحال حاضر در کدام قسمت زمانی پخش هستیم) همچنین باید بتوانیم با تغییر وضعیت آن، قسمت دلخواه خودمون رو بشنویم4. Textبرای نمایش ثانیه و دقیقه لحظه ای هنگام پخش استفاده میکنیم 5. Buttonیک دکمه ساده برای play و pauseخب تا اینجا کار اصلیمون رو هنوز شروع نکردیم ولی قبل از اون بیاید یه تغییر کوچیک تو صفحه ایجاد کنیم برای تغییر نوشته یک دکمه به راحتی میتونیم روی اون کلیک کرده و از منوی سمت راست با تغییر Text، متن داخل اون رو شخصی سازی کنیم ولی اگه بخوایم شکل به خصوصی (مثلا دایره ای ) به یکی از دکمه ها بدیم چی؟ یا مثلا رنگش رو چه طور عوض کنیم؟جاوا اف ایکس از نوعی css خاصی پشتیبانی میکنه که به ما این قابلیت رو میده ظاهر کاپوننت های خودمون رو شخصی سازی کنیم. این ویژگی به ما کمک میکنه تا رابط های کاربری با ظاهر چشم نوازی ایجاد کنیم (بر خلاف Swing که کامپوننت های قدیمیش واقعا تو ذوق آدم میزد :) )در حال حاضر صرفا برای شروع روی دکمه روبروی slider کلیک کرده و از منوی سمت راست قسمت Style، ویژگی خاص fx-background-radius- را به 50% تغییر میدهیم. همچنین میتوانیم از کاراکتر های خاص html که از یونی کد های مختلف شناخته میشن برای دکمه ها استفاده کنیم.3. نوشتن کلاس Controllerاول از همه نیاز داریم به یک سری از کامپوننت های خودمون دسترسی داشته باشیم تا بتونیم تغییراتی رو هنگام اجرا اعمال کنیم پس ویژگی fx:id یکتایی به هر کدوم اختصاص میدیم. همچنین باید یکسری event (رویداد)هایی مشخص کنیم تا هنگام وقوع اونها بتونیم تغییرات را اعمال کنیم مثلا اینکه وقتی کاربر روی دکمه ای کلیک میکنه چه اتفاقی رخ بده یا اینکه موقع تغییر دادن مکان نمای slider بتونیم وضعیت پخش رو تغییر بدهیم. برای این کارها کافیه روی کامپوننت مورد نظر کلیک کرده و از قسمت سمت راست منوی code موارد زیر را تعریف کنیمکامپوننت هایی که برای آن ها شناسه تعیین میکنیم1. اسلایدر2. کلید پخش3. نمایشگر زمانرویداد ها1. Action event برای هر کدام از کلید های file و play2. همچنین یک on mouse dragged برای اسلایدرخب کارمون تقریبا با scene builder تموم شد بعد از اینکه view رو در مسیر پروژه به جای Sample.fxml کپی کردیم (فراموش نکنید ویژگی fx:controller رو در فایل fxml برابر مسیر و نام کلاس کنترلر قرار بدید)حالا باید کلاس controller خودمون رو بنویسیم برای اینکه کارمون یکم راحتتر بشه از محیط Scene builder مسیرView -> Show Sample Controller Skeletonیک نسخه اولیه از کلاس کنترلر میگیریم که شامل کامپوننت ها و رویداد هایی است که تعریف کردیم. همگی را در کلاس Controller کپی میکنیمکامپوننت هایی که شناسه یکتایی بهشون دادیم همگی با انوتیشن FXML@ مشخص می شوند و نیازی به نمونه سازی اولیه ندارند.خب اینجا ما علاوه بر مواردی که در بالا با انوتیشن مشخص شده اند به یک سری کلاس های بیشتری هم نیاز داریم: MediaPlayer File همچنین یک متغیر boolean برای تمایز بین حالت پخش و سکونpublic class Controller { @FXML private Slider slider; @FXML private Button playButton; @FXML private Text timeLabel; private MediaPlayer mediaPlayer; private File file; private boolean isPlaying = false; ... } اگه بخوایم از دید کاربر به مساله نگاه کنیم برای شروع کار نیاز داریم فایل مورد نظرمون رو انتخاب کنیم یک پیاده سازی ابتدایی که میتوانیم ارائه دهیم در متد Action event برای کلید file:@FXML void openFile(ActionEvent event) { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle(&quotSelect your music&quot); file = fileChooser.showOpenDialog(new Stage()); Media media = new Media(file.toURI().toString()); mediaPlayer = new MediaPlayer(media); }هرچه بیشتر درگیر جزئیات شویم میتونیم این قطعه کد رو کاملتر کنیم مثلا در ادامه نیاز داریم که به media player بگیم که هنگام پخش مکان نمای اسلایدر رو در جای مناسب قرار بده پس در همین متد قطعه کد زیر را هم داریمmediaPlayer.setOnPlaying(new Runnable() { @Override public void run() { new Thread(()->{ while (isPlaying){ slider.setValue(mediaPlayer.getCurrentTime().toSeconds() / mediaPlayer.getStopTime().toSeconds() * 100); try { Thread.currentThread().sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }); میبینید که برای کارمون مجبور شدیم یک ترد(Thread) جدید هم ایجاد کنیم و در آخر برای اینکه تردمون همیشه درگیر نباشه یک sleep کوتاه هم براش میگذاریم (این کار باعث میشه تا بتونیم مکان نمای اسلایدر رو تغییر بدیم و گرنه تردمون زورش از ما خیلی بیشتر میشه ).برای Action event کلید play:@FXML void playClicked(ActionEvent event) { if(isPlaying){ mediaPlayer.pause(); playButton.setText(&quot⏵&quot); } else{ mediaPlayer.play(); playButton.setText(&quot||&quot); } isPlaying = !isPlaying; } و همچنین برای رویداد کشیدن Slider:@FXML public void sliderDragged(MouseEvent mouseEvent) { mediaPlayer.seek(new Duration(slider.getValue() * mediaPlayer.getStopTime().toSeconds() * 10)); } توجه کنید که موارد بالا صرفا برای پیاده سازی اولیه میباشند. همونطور که گفتم هر چی بیشتر درگیر جزئیات بشیم کاملترش میکنیمسورس کد در گیتهاب