элементы обновления javafx 2.1 tableview

<p>у меня есть эта общая проблема, как кажется. мой табличный вид не обновит мои элементы после их сброса. я проверил данные, и это новый. </p><p><strong> я пробовал несколько решений из интернета, но безуспешно. </strong> </p><p>невозможно сбросить все столбцы, потому что он добавляет одну пустую дополнительную (не знаю почему), а изменение размера просто прерывается.</p><p>моя таблица не<strong> редактируемая </strong>. новые данные изменены.</p><p>данные обновляются, если я<strong> изменяю порядок </strong>элементов, а строки меняются (: |).</p><p>я просто остался без идей.</p><p>на данный момент код обновления довольно прост.</p><pre><code>observablelist<user> data = fxcollections.observablearraylist(user.getresellers()); reseller\_table.setitems(data); </code></pre><p>снова новые данные верны. когда я делаю выбор к tableview, он возвращает новый правильный item.</p>

<p>у меня была похожая проблема с обновлением. мое решение состояло в том, чтобы ограничить операции с <code>observablelist</code> теми, которые корректно работают с <code>bind()</code>.</p><p>предположим, что <code>observablelist obslist</code> является базовым списком для <code>tableview</code>. </p><p><em>затем</em><br> <code>obslist.clear()</code> (унаследованная от <code>java.util.list<></code>) будет<strong> не обновляться </strong><code>tableview</code> правильно, но.</p><p>также вызов <code>setitem(obslist)</code> сделал<strong> не работает </strong>для запуска обновления ... но ...</p><p><code>obslist.removeall(obslist)</code> (перезаписывается <code>observablelist</code>)<strong> работает нормально </strong>потому что корректно запускает changeevent.</p><p>пополнение списка с совершенно новым содержанием тогда работает следующим образом:</p><ul> <li><code>obslist.removeall(obslist);</code></li> <li><code>obslist.add(...); //e.g. in a loop...</code></li> </ul><p>или же</p><ul> <li><code>obslist.removeall(obslist);</code></li> <li><code>fxcollections.copy(obslist, somesourcelist)</code></li> </ul><p>с наилучшими пожеланиями инго</p>

<p>временное решение:</p><pre><code> tableview.getcolumns().get(0).setvisible(false); tableview.getcolumns().get(0).setvisible(true); </code></pre>

<p>поскольку <code>javafx 8u60</code> вы можете использовать (при условии, что <code>tableview</code> является экземпляром <a href="https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/tableview.html">tableview</a> class):</p><pre><code>tableview.refresh(); </code></pre><p>из документации:</p><blockquote> <p>вызов refresh () заставляет элемент управления tableview воссоздать и заселить клетки, необходимые для заполнения визуальных границ контроль. другими словами, это заставляет tableview обновлять то, что он показывает пользователю. это полезно в тех случаях, когда основной источник данных изменился таким образом, который не наблюдается в tableview сам.</p> </blockquote>

<p><strong>обновление:</strong><br> наконец, обновление табличного представления разрешено в <strong>javafx 8u60</strong>, который доступен для раннего доступа.</p><hr><p>об обновлении смотрите <a href="https://stackoverflow.com/q/10912690/682495">обновление строк в tableview</a> .<br> а о пустом столбце см. <a href="https://stackoverflow.com/q/11033404/682495">javafx 2 create tableview с одним столбцом</a> . по сути, это не столбец, то есть вы не можете выбрать элемент, щелкнув по элементам этого пустого столбца. это просто пустое место в стиле строки.</p><hr><p><strong>update:</strong> если вы обновляете tableview с помощью <code>reseller\_table.setitems(data)</code>, вам не нужно использовать <code>simplestringproperty</code>. было бы полезно, если бы вы обновляли только одну строку/элемент. вот полный рабочий пример обновления данных таблицы: </p><pre><code>import java.util.arraylist; import java.util.list; import javafx.application.application; import javafx.collections.fxcollections; import javafx.event.actionevent; import javafx.event.eventhandler; import javafx.scene.group; import javafx.scene.scene; import javafx.scene.control.button; import javafx.scene.control.tablecolumn; import javafx.scene.control.tableview; import javafx.scene.control.cell.propertyvaluefactory; import javafx.scene.layout.vbox; import javafx.stage.stage; public class dddeb extends application { public static class product { private string name; private string code; public product(string name, string code) { this.name = name; this.code = code; } public string getcode() { return code; } public void setcode(string code) { this.code = code; } public string getname() { return name; } public void setname(string name) { this.name = name; } } private tableview<product> producttable = new tableview<product>(); @override public void start(stage stage) { button refreshbtn = new button("refresh table"); refreshbtn.setonaction(new eventhandler<actionevent>() { @override public void handle(actionevent arg0) { // you can get the new data from db list<product> newproducts = new arraylist<product>(); newproducts.add(new product("new product a", "1201")); newproducts.add(new product("new product b", "1202")); newproducts.add(new product("new product c", "1203")); newproducts.add(new product("new product d", "1244")); producttable.getitems().clear(); producttable.getitems().addall(newproducts); //producttable.setitems(fxcollections.observablearraylist(newproducts)); } }); tablecolumn namecol = new tablecolumn("name"); namecol.setminwidth(100); namecol.setcellvaluefactory(new propertyvaluefactory<product, string>("name")); tablecolumn codecol = new tablecolumn("code"); codecol.setcellvaluefactory(new propertyvaluefactory<product, string>("code")); producttable.getcolumns().addall(namecol, codecol); producttable.setcolumnresizepolicy(tableview.constrained\_resize\_policy); // you can get the data from db list<product> products = new arraylist<product>(); products.add(new product("product a", "0001")); products.add(new product("product b", "0002")); products.add(new product("product c", "0003")); //producttable.getitems().addall(products); producttable.setitems(fxcollections.observablearraylist(products)); final vbox vbox = new vbox(); vbox.setspacing(5); vbox.getchildren().addall(producttable, refreshbtn); scene scene = new scene(new group()); ((group) scene.getroot()).getchildren().addall(vbox); stage.setscene(scene); stage.setwidth(300); stage.setheight(500); stage.show(); } public static void main(string[] args) { launch(args); } } </code></pre><p>обратите внимание, что</p><pre><code>producttable.setitems(fxcollections.observablearraylist(newproducts)); </code></pre><p>а также </p><pre><code>producttable.getitems().clear(); producttable.getitems().addall(newproducts); </code></pre><p>почти эквивалентны. таким образом, я использовал тот, чтобы заполнить таблицу в первый раз, и другой, когда таблица обновляется. это только для демонстрационных целей. я проверил код в javafx 2.1. и, наконец, вы можете (и должны) отредактировать свой вопрос, чтобы улучшить его, переместив фрагменты кода в своем ответе на свой вопрос.</p>

<p>я наконец нашел уродливый обходной путь, чтобы обновить все строки.</p><pre><code>void refreshtable() { final list<item> items = tableview.getitems(); if( items == null || items.size() == 0) return; final item item = tableview.getitems().get(0); items.remove(0); platform.runlater(new runnable(){ @override public void run() { items.add(0, item); } }); } </code></pre>

<p>кажется, есть несколько отдельных проблем вокруг olditems.equals (newitems)</p><p>первая часть <a href="https://javafx-jira.kenai.com/browse/rt-22463">rt-22463</a> : tableview не будет обновляться даже при вызове items.clear ()</p><pre><code>// refresh table table.getitems().clear(); table.setitems(listequaltoold); </code></pre><p>это исправлено очистка старых элементов перед установкой нового списка очищает все старое состояние, таким образом обновляя таблицу. любой пример, где это не работает, может быть регрессией.</p><p>что еще не работает, так это переустанавливать элементы без предварительной очистки</p><pre><code>// refresh table table.setitems(listequaltoold); </code></pre><p>это проблема, если в таблице показаны свойства, которые не участвуют в одинаковом решении элемента (см. пример в <a href="https://javafx-jira.kenai.com/browse/rt-22463">rt-22463</a> или <a href="http://pastebin.com/qknvzxtd">aubin's</a> ) и покрыты - мы надеемся - <a href="https://javafx-jira.kenai.com/browse/rt-39094">rt -39094</a> </p><p><strong>update</strong>: <a href="https://javafx-jira.kenai.com/browse/rt-39094">rt-39094</a> последний также исправлен, для 8u40! должен всплыть в ea через пару недель, спекулируя на u12 или около того. </p><p>техническая причина, по-видимому, заключается в проверке на равенство в реализации ячейки: для исправления проблем с производительностью была введена проверка изменений элемента перед фактическим вызовом updateitem (t, boolean). разумно, просто жестко закодировать «изменить» == old.equals (new) создает проблемы в некоторых контекстах. </p><p>обходной путь для меня (без формального тестирования!) - это пользовательский tablerow, который включается, если требуется проверка личности:</p><pre><code>/** * extended tablerow that updates its item if equal but not same. * needs custom skin to update cells on invalidation of the * item property.<p> * * looks ugly, as we have to let super doing its job and then * re-check the state. no way to hook anywhere else into super * because all is private. <p> * * super might support a configuration option to check against * identity vs. against equality.<p> * * note that this is \_not\_ formally tested! any execution paths calling * <code>updateitem(int)</code> other than through * <code>indexedcell.updateindex(int)</code> are not handled. * * @author jeanette winzenburg, berlin */ public class identitycheckingtablerow<t> extends tablerow<t> { @override public void updateindex(int i) { int oldindex = getindex(); t olditem = getitem(); boolean wasempty = isempty(); super.updateindex(i); updateitemifneeded(oldindex, olditem, wasempty); } /** * here we try to guess whether super updateindex didn't update the item if * it is equal to the old. * * strictly speaking, an implementation detail. * * @param oldindex cell's index before update * @param olditem cell's item before update * @param wasempty cell's empty before update */ protected void updateitemifneeded(int oldindex, t olditem, boolean wasempty) { // weed out the obvious if (oldindex != getindex()) return; if (olditem == null || getitem() == null) return; if (wasempty != isempty()) return; // here both old and new != null, check whether the item had changed if (olditem != getitem()) return; // unchanged, check if it should have been changed t listitem = gettableview().getitems().get(getindex()); // update if not same if (olditem != listitem) { // doesn't help much because itemproperty doesn't fire // so we need the help of the skin: it must listen // to invalidation and force an update if // its super wouldn't get a changeevent updateitem(listitem, isempty()); } } @override protected skin<?> createdefaultskin() { return new tablerowskinx<>(this); } public static class tablerowskinx<t> extends tablerowskin<t> { private weakreference<t> olditemref; private invalidationlistener iteminvalidationlistener; private weakinvalidationlistener weakiteminvalidationlistener; /** * @param tablerow */ public tablerowskinx(tablerow<t> tablerow) { super(tablerow); olditemref = new weakreference<>(tablerow.getitem()); iteminvalidationlistener = o -> { t newitem = ((observablevalue<t>) o).getvalue(); t olditem = olditemref != null ? olditemref.get() : null; olditemref = new weakreference<>(newitem); if (olditem != null && newitem != null && olditem.equals(newitem)) { forcecellupdate(); } }; weakiteminvalidationlistener = new weakinvalidationlistener(iteminvalidationlistener); tablerow.itemproperty().addlistener(weakiteminvalidationlistener); } /** * try to force cell update for equal (but not same) items. * c&p'ed code from tablerowskinbase. */ private void forcecellupdate() { updatecells = true; getskinnable().requestlayout(); // update the index of all children cells (rt-29849). // note that we do this after the tablerow item has been updated, // rather than when the tablerow index has changed (as this will be // before the row has updated its item). this will result in the // issue highlighted in rt-33602, where the table cell had the correct // item whilst the row had the old item. final int newindex = getskinnable().getindex(); for (int i = 0, max = cells.size(); i < max; i++) { cells.get(i).updateindex(newindex); } } } @suppresswarnings("unused") private static final logger log = logger .getlogger(identitycheckinglistcell.class.getname()); } // usage table.setrowfactory(p -> new identitycheckingtablerow()); </code></pre><p>обратите внимание, что tablecell имеет аналогичную жестко проверенную проверку на равенство, поэтому, если пользовательской строки недостаточно, может потребоваться использование настраиваемого tablecell с аналогичным обходным решением (хотя не сталкивайтесь с примером, где это необходимо)</p>

<p>я полагаю <a href="https://forums.oracle.com/forums/thread.jspa?threadid=2382342">этот поток</a> имеет очень хорошее описание проблемы с обновлением таблицы.</p>

<p>решение пользователя user1236048 является правильным, но ключевой момент не вызван. в ваших классах pojo, используемых для наблюдаемого списка таблицы, вы должны не только устанавливать методы getter и setter, но и новый, называемый property. в руководстве по просмотру таблиц oracle ( <a href="http://docs.oracle.com/javafx/2/ui\_controls/table-view.htm">http://docs.oracle.com/javafx/2/ui\_controls/table-view.htm</a> ) они оставили эту ключевую часть отключенной!</p><p>вот как должен выглядеть класс person:</p><pre><code>public static class person { private final simplestringproperty firstname; private final simplestringproperty lastname; private final simplestringproperty email; private person(string fname, string lname, string email) { this.firstname = new simplestringproperty(fname); this.lastname = new simplestringproperty(lname); this.email = new simplestringproperty(email); } public string getfirstname() { return firstname.get(); } public void setfirstname(string fname) { firstname.set(fname); } public simplestringproperty firstnameproperty(){ return firstname; } public string getlastname() { return lastname.get(); } public void setlastname(string fname) { lastname.set(fname); } public simplestringproperty lastnameproperty(){ return lastname; } public string getemail() { return email.get(); } public void setemail(string fname) { email.set(fname); } public simplestringproperty emailproperty(){ return email; } </code></pre><p>}</p>

<p>у меня есть случай, когда ничто другое не помогло как решение от aubin. я адаптировал метод и изменил его, удалив и добавив элемент в список элементов таблиц, так как в итоге он работает только надежно с этим хаком, столбец видимого переключателя выполнил задание только в первый раз.</p><p>я сообщил об этом также в задании jira: <a href="https://javafx-jira.kenai.com/browse/rt-22463">https://javafx-jira.kenai.com/browse/rt-22463</a> </p><pre><code> public <t> void tableitemsrefresh(final observablelist<t> items) { if (items == null || items.size() == 0) return; int idx = items.size() -1; final t item = items.get(idx); items.remove(idx); new timer().schedule(new timertask() { @override public void run() { platform.runlater(new runnable() { @override public void run() { items.add(item); } }); } }, 100); } </code></pre>

<p>посмотрите на эту проблему в jira: <a href="https://bugs.openjdk.java.net/browse/jdk-8098085">https://bugs.openjdk.java.net/browse/jdk-8098085</a> </p><p>комментарий 2012-09-20 08:50 дал обходной путь, который работает.</p><pre><code>//wierd javafx bug reseller\_table.setitems(null); reseller\_table.layout(); observablelist<user> data = fxcollections.observablearraylist(user.getresellers()); reseller\_table.setitems(data); </code></pre>

<p>у меня была такая же проблема, и после некоторых поисков это мой обходной путь. я обнаружил, что если столбцы удаляются, а затем повторно добавляются, таблица обновляется.</p><pre><code>public static <t,u> void refreshtableview(final tableview<t> tableview, final list<tablecolumn<t,u>> columns, final list<t> rows) { tableview.getcolumns().clear(); tableview.getcolumns().addall(columns); observablelist<t> list = fxcollections.observablearraylist(rows); tableview.setitems(list); } </code></pre><p><br/> пример использования:<br/></p><pre><code>refreshtableview(mytableview, arrays.aslist(col1, col2, col3), rows); </code></pre>

<p>вместо того, чтобы обновлять вручную, вы должны использовать наблюдаемые свойства . ответы на этот вопрос иллюстрируют цель: <a href="https://stackoverflow.com/questions/13381067/simplestringproperty-and-simpleintegerproperty-tableview-javafx">simplestringproperty и simpleintegerproperty tableview javafx</a> </p>

<p>на основании ответа даниэля леона </p><pre><code>public static void refresh\_table(tableview table) { for (int i = 0; i < table.getcolumns().size(); i++) { ((tablecolumn)(table.getcolumns().get(i))).setvisible(false); ((tablecolumn)(table.getcolumns().get(i))).setvisible(true); } } </code></pre>

<p><strong> javafx8 </strong></p><p>я добавляю новый элемент с помощью dialogbox. вот мой код.</p><pre><code>observablelist<area> area = fxcollections.observablearraylist(); </code></pre><p><strong> при инициализации () или setapp () </strong></p><pre><code>this.areatable.setitems(getareadata()); </code></pre><p><strong> getareadata () </strong></p><pre><code>private observablelist<area> getareadata() { try { area = areadao.searchemployees(); // to inform observablelist return area; } catch (classnotfoundexception | sqlexception e) { system.out.println("error: " + e); return null; } } </code></pre><p>добавить по диалоговому окну.</p><pre><code>@fxml private void handlenewarea() { area temparea = new area(); boolean okclicked = showareadialog(temparea); if (okclicked) { addnewarea(temparea); this.area.add(temparea); // to inform observablelist } } </code></pre><p><code>area</code> - это обычный javafx pojo . надеюсь, это кому-нибудь поможет. </p>

<p>что за ошибка! вот еще один обходной путь ...</p><pre><code>public void forcerefresh() { final tablecolumn< prospect, ? > firstcolumn = view.getcolumns().get( 0 ); firstcolumn.setvisible( false ); new timer().schedule( new timertask() { @override public void run() { platform.runlater( new runnable() { @override public void run() { firstcolumn.setvisible( true ); }}); }}, 100 ); } </code></pre><p>я сделал <a href="http://sscce.org/">sscce</a> to <a href="http://pastebin.com/qknvzxtd">показать ошибку</a> . я призываю всех исправить это другим, более элегантным способом, потому что мой обходной путь очень уродлив!</p>

<p>та же самая проблема здесь, я попробовал некоторые решения, и лучшее для меня следующее:</p><p>в методе initialize контроллера создайте пустой observablelist и установите его в таблице:</p><pre><code> obsbericht = fxcollections.observablelist(new arraylist<bericht>(0)); tblbericht.setitems(obsbericht); </code></pre><p>в вашем методе обновления просто используйте observablelist, очистите его и добавьте обновленные данные:</p><pre><code> obsbericht.clear(); obsbericht.addall(fxcollections.observablelist(databasehelper.getberichte())); // tblbericht.setitems(obsbericht); </code></pre><p>нет необходимости снова устанавливать элементы таблицы</p>

<p>я не уверен, относится ли это к вашей ситуации, но я опубликую то, что сработало для меня.</p><p>я меняю свое табличное представление на основе запросов/поисков в базе данных. например, таблица базы данных содержит данные пациента. мое начальное представление таблицы в моей программе содержит всех пациентов. затем я могу выполнить поиск запроса для пациентов по имени и фамилии. я использую результаты этого запроса, чтобы пополнить свой список наблюдаемых. затем я сбрасываю элементы в табличном представлении, вызывая tableview.setitems (observablelist):</p><pre><code>/** * searches the table for an existing patient. */ @fxml public void handlesearch() { string fname = this.fnamesearch.gettext(); string lname = this.lnamesearch.gettext(); localdate bdate = this.bdatesearch.getvalue(); if (this.nameanddobsearch(fname, lname, bdate)) { this.patientdata = this.controller.processnursepatientsearch(fname, lname, bdate); } else if (this.birthdatesearch(fname, lname, bdate)) { this.patientdata = this.controller.processnursepatientsearch(bdate); } else if (this.namesearch(fname, lname, bdate)) { this.patientdata = this.controller.processnursepatientsearch(fname, lname); } this.patienttable.setitems(this.patientdata); } </code></pre><p>блоки if обновляют observablelist с результатами запроса.</p>

<p>мое решение похоже на обходной путь <a href="https://stackoverflow.com/users/980442/">даниэль де леон</a> , но оно также работает, когда вам нужно скрыть первый столбец (индекс 0 в его примере). конечно, вы можете просто изменить индекс в его решении, но если вы переставляете столбцы, моё решение может работать лучше для вас. идея состоит в том, чтобы скрыть и показать столбец по имени, а не скрывать и показывать его по индексу: </p><pre><code>private void updatemytableview() { // update table view workaround !!! if (mytableview != null) { observablelist<tablecolumn<entry, ?>> columns = mytableview.getcolumns(); for (tablecolumn<entry, ?> column : columns) { // at this point, we look for the specific column, which should // always be visible // therefore we use the "column title" string, e.g. "first name" if (column.gettext().equals("column title")) { column.setvisible(false); column.setvisible(true); } } } } </code></pre><p>лучше всего обновить таблицу в ветке обновления пользовательского интерфейса. однако он также работает, просто вызывая <code>updatemytableview();</code> после того, как вы что-то изменили в своей таблице, поскольку javafx, похоже, обновляется в потоке пользовательского интерфейса в любом случае (не уверен в этом).</p><pre><code>platform.runlater(new runnable() { public void run() { updatemytableview(); } }); </code></pre>

<p>метод initialize ()</p><pre><code>fullnamecolumn = new tablecolumn("full name"); fullnamecolumn.setcellvaluefactory(new propertyvaluefactory<user, string>("fullname")); usernamecolumn = new tablecolumn("username"); usernamecolumn.setcellvaluefactory(new propertyvaluefactory<user, string>("test")); emailcolumn = new tablecolumn("email"); emailcolumn.setcellvaluefactory(new propertyvaluefactory<user, string>("email")); reseller\_table.setcolumnresizepolicy(tableview.constrained\_resize\_policy); reseller\_table.getcolumns().addall(usernamecolumn, fullnamecolumn, emailcolumn); observablelist<user> data = fxcollections.observablearraylist(user.getresellers()); reseller\_table.setitems(data); </code></pre><p>пользовательский класс (hibernate pojo class)</p><pre><code>private simplestringproperty test; public void setfullname(string fullname) { this.fullname = fullname; this.test = new simplestringproperty(fullname); } public simplestringproperty testproperty() { return test; } </code></pre><p>метод refresh ()</p><pre><code>observablelist<user> data = fxcollections.observablearraylist(user.getresellers()); reseller\_table.setitems(data); </code></pre>

<p>я знаю, что этому вопросу 4 года, но у меня та же проблема, я пробовал решения сверху и не работал. я также вызвал метод refresh (), но все еще не ожидаемый результат. поэтому я выложу здесь мое решение, может быть, кому-то поможет.</p><pre><code>question db = center.getselectionmodel().getselecteditem(); new questioncrud().deleteq(db.getid()); observablelist<question> aftdelete = fxcollections.observablearraylist( (new questioncrud()).all() ); center.setitems(aftdelete); </code></pre><p>несмотря на то, что до этого я использовал другую переменную в obeservablelist для установки элементов в табличное представление, я называю это «грязным методом», но пока не получу лучшее решение, все в порядке.</p>

<p>после ответа даниэля де леона ... </p><ul> <li>я ввел фиктивное свойство "modelchangedproperty" в моей модели и </li> <li>создал метод refresh () в моей модели, который изменяет значение этого свойства.</li> <li>в моем контроллере я добавил listener в свойство dummy, которое обновляет табличное представление. </li> </ul><p>-</p><pre><code>/** * adds a listener to the modelchangedproperty to update the table view */ private void createupdateworkaroundlistener() { model.modelchangedproperty.addlistener( (observablevalue<? extends boolean> arg0, final boolean oldvalue, final boolean newvalue) -> updatetableview() ); } /** * work around to update table view */ private void updatetableview() { tablecolumn<?, ?> firstcolumn = scenariotable.getcolumns().get(0); firstcolumn.setvisible(false); firstcolumn.setvisible(true); } </code></pre>

<p>я пытался найти способ обновить tableview (scalafx) в течение 3-4 часов. наконец я получил ответ. я просто хочу опубликовать свое решение, потому что я потратил впустую уже несколько часов. </p><p>-для извлечения строк из базы данных я использовал для объявления метода, который возвращает observablebuffer.</p><p>мой jdbc класс</p><pre><code> //to get all customer details def getcustomerdetails : observablebuffer[customer] = { val customerdetails = new observablebuffer[customer]() try { val resultset = statement.executequery("select * from musteribilgileri") while (resultset.next()) { val musteriid = resultset.getstring("musteriid") val musteriismi = resultset.getstring("musteriismi") val urununtakildigitarih = resultset.getdate("urununtakildigitarih").tostring val bakimtarihi = resultset.getdate("bakimtarihi").tostring val urununismi = resultset.getstring("urununismi") val telno = resultset.getstring("telno") val aciklama = resultset.getstring("aciklama") customerdetails += new customer(musteriid,musteriismi,urununtakildigitarih,bakimtarihi,urununismi,telno,aciklama) } } catch { case e => e.printstacktrace } customerdetails } </code></pre><p>-и я создал объект tableview. </p><pre><code>var table = new tableview[customer](model.getcustomerdetails) table.columns += (customeridcolumn,customernamecolumn,productinstallcolumn,servicedatecolumn, productnamecolumn,phonenocolumn,detailcolumn) </code></pre><p>-и наконец я получил решение. в кнопку обновления, я вставил этот код; </p><pre><code>table.setitems(fxcollections.observablearraylist(model.getcustomerdetails.delegate)) </code></pre><p>модель является ссылкой на мой класс соединения jdbc</p><pre><code>val model = new scalajdbcconnectselect </code></pre><p>это коды скаляпа, но это дает некоторое представление о javafx</p>

<p>хорошо после поиска всех возможных решений. сначала попытался очистить данные, а затем добавил в tableview <code>tableview.getitems().clear();</code>, что не решило мою проблему. я перепробовал все ответы, приведенные здесь, но у меня ничего не вышло, и у меня все еще были устаревшие объекты в моей таблице, как показано на рисунке ниже:</p><p> <a href="https://i.stack.imgur.com/nmu11.png"> <img src="https://i.stack.imgur.com/nmu11.png" alt="enter image description here"> </a> </p><p>чтобы исправить это, я создал метку dummy и использовал <code>setgraphic</code> следующим образом:</p><p> <a href="https://i.stack.imgur.com/vng28.png"> <img src="https://i.stack.imgur.com/vng28.png" alt="enter image description here"> </a> </p>